(ReactJS)“警告:组件正在将不受控制的输入更改为受控制。这可能是由未定义的值更改引起的......”

Osm*_*luk 5 javascript warnings userform reactjs react-component

由另一个控制器控制的用户窗体在控制台上抱怨为

“警告:组件正在将不受控的输入更改为受控。这可能是由于值从未定义的值更改为已定义的值引起的,这种情况不应该发生。在组件的生命周期内决定使用受控或不受控的输入元素。更多信息: https: //reactjs.org/link/control-components 输入跨度 li ul..."**

这是组件代码:

export default({user}) => {
  if(!user) {
    return <div></div>
  } else {
    const [name,setName] = useState(user.name|| "")
    useEffect(() => {
      setName(user.name);
    }, [user])
              
    return <form>
             <fieldset> 
               <legend> Edit  {user.name }</legend>
               <p> 
                 <label htmlFor={"name"}> Name  </label>
                 <input  id="name" value={name || ""} onChange={e => setName(e.target.value)} />
               </p> 
             </fieldset>
           </form>
  }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了其他 stackoverflow 答案中建议的所有修复,但仍然发出警告。
我可能缺少什么吗?

Sab*_*dar 10

实际上,当你遇到这个问题时,这是受控组件和非受控组件的错误,简单来说:受控组件:是使用状态来更改其值的组件。 例子

<input
onChange={(e)=>{whatever!}
value={from your state}
/>
Run Code Online (Sandbox Code Playgroud)

而在不受控制的组件中,状态并不涉及太多,您可以简单地使用defaultValue或ref。 例子

<input
defaultValue={from your state or from anywhere}
/>
Run Code Online (Sandbox Code Playgroud)

请记住:如果您同时使用 value 和 defaultValue ,则会出现错误,因为我们不能同时使用受控组件的 value 和不受控组件的 defaultValue 。

提示:您需要在受控组件和非受控组件之间进行选择,因此使用 ref 将是解决方案。 将值更改为defaultValue 将解决该问题。

笔记:

defaultValue仅适用于初始负载。如果你想初始化输入,那么你应该使用defaultValue,但如果你想使用状态来改变值,那么你需要使用value。阅读此内容以了解更多信息React 输入 defaultValue 不会随状态更新

我在输入中使用了以下方法来消除该警告,通过使用短路评估来定义 value 属性,如下所示:

value={this.state.fields.name || ''}   // (undefined || '') = ''
Run Code Online (Sandbox Code Playgroud)

另一种方法

原因是,在您定义的状态下:

this.state = { fields: {} }
Run Code Online (Sandbox Code Playgroud)

fields 作为空白对象,因此在第一次渲染期间this.state.fields.name将为undefined,输入字段的值将为:

value={undefined}
Run Code Online (Sandbox Code Playgroud)

因此,输入字段将变得不受控制。

一旦您在输入中输入任何值,fields状态就会更改为:

this.state = { fields: {name: 'xyz'} }
Run Code Online (Sandbox Code Playgroud)

此时输入字段被转换为受控组件;这就是你收到错误的原因:

组件正在更改要控制的文本类型的不受控制的输入。

可能的解决方案:

1- 将fieldsin 状态定义为:

this.state = { fields: {name: ''} }
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 3

我已经用这个工作示例更新了您的组件。

const { useEffect, useState } = React;

function Example({ user }) {

  const [name, setName] = useState(user.name);

  function handleChange(e) {
    setName(e.target.value);
  }

  useEffect(() => console.log(name), [name]);

  if(!user) return <div></div>;

  return (
    <form>
      <fieldset> 
        <legend>Edit name</legend>
        <input
          id="name"
          value={name}
          onChange={handleChange}
        />
      </fieldset>
    </form>
  )
};

const user = { name: 'Bob' };

ReactDOM.render(
  <Example user={user} />,
  document.getElementById('react')
);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Run Code Online (Sandbox Code Playgroud)