首页 > 解决方案 > 设置通过 props 接收的表单元素初始值

问题描述

我正在使用 React Hooks 来处理一个简单的表单。我收到“交易”对象作为道具,我想根据这个对象设置输入值,因为我正在尝试更新这个“交易”

正如您在下面看到的,我正在尝试根据“交易”对象设置我的描述输入值,我将其作为道具接收

//TransactionsForm.js

const TransactionsForm = ({ onSubmit, transaction }) => {

  const [values, setValues] = useState({
    description: transaction.description
  })

  const handleChange = event => {
    const { name, value } = event.target
    setValues({ ...values, [name]: value })
  }

  return (
    <form>      
          <input
            type="text"
            placeholder="description"
            name="description"
            value={values.description}
            onChange={handleChange}
          /> 
        <button>Submit</button>
    </form>
  )
}

这个“交易”对象最初看起来像这样:

{
    id: null,
    description: '',
    transactionType: '',
    date: '',
    category: '',
    amount: ''
}

但是然后我更新它,当用户单击编辑按钮并将其设置为单击的事务对象以传递给我的 TransactionsForm.js 并因此基于此更新表单输入值。

如果我这样设置我的输入值

<input
   type="text"
   placeholder="description"
   name="description"
   value={transaction.description} // like this it's working, but when I use values.description the value is not updating
   onChange={handleChange}
/> 

标签: reactjsformsreact-hooks

解决方案


TransactionsForm我猜您在道具更改时更新值有问题。useState仅在第一次渲染时设置初始值,并且在道具更改时不会更新它。您需要手动执行此操作:

const TransactionsForm = ({ onSubmit, transaction }) => {

  const [values, setValues] = useState({
    description: transaction.description
  });

  useEffect(() => setValues(
    oldValues => (
      {...oldValues, description: transaction.description}
    )
  ), [transaction.description]);

  ...

useEffect将在初始渲染时调用,并且每次transaction.description都会获得一个新值。由于setValues收到一个新对象,您将在初始对象之后获得不必要的额外渲染。为避免这种情况,您只能将 存储description在您的状态中:

const [descripton, setDescription] = useState(transaction.description);

如果您确实需要复杂的状态结构,请考虑使用useReducer并将“oldProps”与useRef一起存储:

const TransactionsForm = ({ onSubmit, transaction }) => {

  const [values, setValues] = useState({
    description: transaction.description
  });
  const oldDescription = useRef(transaction.description);

  useEffect(() => {
    if (oldDescription.current !== transaction.description) {
      oldDescription.current = transaction.description;
      setValues(
        oldValues => (
          {...oldValues, description: transaction.description}
        )
      );
    }
 }, [transaction.description]);

  ...

推荐阅读