You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React 18中textarea onChange更新状态异常:输入字符自动消失求助

React 18中Textarea输入字符自动消失的解决方案

问题现象

跟随旧教程开发React笔记应用时,在textarea中输入字符后,字符会先显示随即被自动删除。

问题分析

从你的代码来看,核心问题出在useEffect的依赖项设置:

  • 你将{id}作为依赖项传入useEffect的数组中,由于每次组件渲染时都会创建新的对象(即使id值未变化),导致useEffect被频繁触发,不断调用getNote从服务器拉取原始笔记数据,直接覆盖了你通过输入更新的note状态,最终造成输入字符被立即重置。

修复方案

1. 修正useEffect依赖项

将依赖项从[{id}]改为[id],id是基础类型(字符串/数字),只有当id值真正变化时,useEffect才会重新执行:

useEffect(() => {
    getNote()
}, [id]) // 此处改为[id]

2. 优化状态更新(可选)

使用React函数式更新方式修改note状态,避免潜在的 stale state 问题,在频繁输入场景下更可靠:

<textarea 
    onChange={(e) => { 
        // 基于上一次状态进行修改
        setNote(prevNote => ({...prevNote, body: e.target.value})) 
    }} 
    value={note?.body}
/>

3. 修复React Router跳转逻辑(可选)

若后续需要实现点击箭头返回首页的功能,注意React Router v6不再通过props传递history,需使用useNavigate钩子:

import { useNavigate } from 'react-router-dom';

const NotePage = () => {
    const navigate = useNavigate();
    // ...其他代码
    const handleSubmit = async () => {
        await updateNote();
        navigate('/');
    };
}

完整修复后的代码示例

import React, { useState, useEffect } from 'react'
import { useParams, useNavigate, Link } from 'react-router-dom'
import { ReactComponent as ArrowLeft } from '../assets/arrow-left.svg'

const NotePage = () => {
    const { id } = useParams();
    const navigate = useNavigate();
    const [note, setNote] = useState(null);

    useEffect(() => {
        getNote();
    }, [id]);

    const getNote = async () => {
        const response = await fetch(`http://localhost:8000/notes/${id}`);
        const data = await response.json();
        setNote(data);
    };

    const updateNote = async () => {
        await fetch(`http://localhost:8000/notes/${id}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({...note, updated: new Date()})
        });
    };

    const handleSubmit = async () => {
        await updateNote();
        navigate('/');
    };

    return (
        <div className="note">
            <div className="note-header">
                <h3>
                    <Link to="/" onClick={handleSubmit}>
                        <ArrowLeft />
                    </Link>
                </h3>
            </div>

            <textarea 
                onChange={(e) => { 
                    setNote(prevNote => ({...prevNote, body: e.target.value})) 
                }} 
                value={note?.body}
            />
        </div>
    )
}

export default NotePage

内容的提问来源于stack exchange,提问作者Laura Pasqualone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:02:08