使用来自 Redux 状态的数据更新功能组件本地状态

IT技术 reactjs redux react-hooks react-functional-component
2021-05-19 09:59:16

我正在构建联系人管理器。当用户单击特定联系人的更新按钮时,将分派一个操作,并使用对象填充减速器状态中的“hotContact”属性。我想要的是用“hotContact”的名称和号码填充 ContactForm 的字段。然而,尽管 hotContact 被加载到 redux 状态,但我的 ContactForm 组件不会显示 hotContact 的名称和号码。我该如何继续?这就是我迄今为止所拥有的。

我尝试在条件块中调用 setFormData 来检查是否存在 hotContact 并且 loadingHotContact 是否为假,但这只会给我一个无限的重新渲染错误。

import React, { useState } from 'react';
import { connect } from 'react-redux';
import { addContact, updateContact } from '../actions/contacts';

const ContactForm = ({
  addContact,
  updateContact,
  contacts: { hotContact, loadingHotContact },
}) => {


  const [formData, setFormData] = useState({
    name:
      hotContact === null && loadingHotContact
        ? ''
        : hotContact.name,
    number:
      hotContact === null && loadingHotContact
        ? ''
        : hotContact.number,
  });

  const onFormDataChange = (event) => {
    setFormData({ ...formData, [event.target.name]: event.target.value });
  };

  const { name, number } = formData;

  const handleSubmit = (event) => {
    event.preventDefault();
    const newContact = { name, number };
    addContact(newContact);
    console.log('Submit the form!');
    setFormData({ name: '', number: '' });
  };

  const handleUpdateSubmit = (event) => {
    event.preventDefault();
    const updatedContact = { name, number };
    updateContact(hotContact._id, updatedContact);
  };


  return !hotContact ? (
    <form onSubmit={handleSubmit}>
      <div>
        Name{' '}
        <input
          type='text'
          name='name'
          value={name}
          onChange={(event) => onFormDataChange(event)}
        />
      </div>
      <div>
        Number{' '}
        <input
          type='text'
          name='number'
          value={number}
          onChange={(event) => onFormDataChange(event)}
        />
      </div>
      <input type='submit' value='Add Contact' />
    </form>
  ) : (
    <form onSubmit={handleUpdateSubmit}>
      <div>
        Name{' '}
        <input
          type='text'
          name='name'
          value={name}
          onChange={(event) => onFormDataChange(event)}
        />
      </div>
      <div>
        Number{' '}
        <input
          type='text'
          name='number'
          value={number}
          onChange={(event) => onFormDataChange(event)}
        />
      </div>
      <input type='submit' value='Apply Changes' />
    </form>
  );
};

const mapStateToProps = (state) => ({
  contacts: state.contacts,
});
export default connect(mapStateToProps, { addContact, updateContact })(
  ContactForm
);
1个回答

这不起作用,因为在第一个渲染器useState是用hotContactfrom props初始化的,但是当您从props接收新值时,状态不会更新(这就是useState钩子的工作方式)

如果你想更新你的状态,你应该使用useEffect钩子:

const ContactForm = ({
  addContact,
  updateContact,
  contacts: { hotContact, loadingHotContact },
}) => {

  const [formData, setFormData] = useState({
    name:
      hotContact === null && loadingHotContact
        ? ''
        : hotContact.name,
    number:
      hotContact === null && loadingHotContact
        ? ''
        : hotContact.number,
  });

  useEffect(() => {
    const {name, number} = props.hotContact;
    setFormData({
      name: name || '',
      number: number || '',
    });
    // execute this
  }, [hotContact]); // when hotContact changes
}

另外,我认为您可以通过这种方式简化您的分配:

const {name, number} = props.hotContact;

setFormData({
  name: name || '',
  number: number || '',
});