使用来自 Redux 状态的数据更新功能组件本地状态 [英] Updating Functional Component Local State Using Data From Redux State

查看:45
本文介绍了使用来自 Redux 状态的数据更新功能组件本地状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

import React, { useState } from 'react';从'react-redux'导入{连接};import { addContact, updateContact } from '../actions/contacts';const ContactForm = ({增加联系人,更新联系方式,联系人:{ hotContact, loadingHotContact },}) =>{const [formData, setFormData] = useState({名称:hotContact === null &&正在加载HotContact?'': hotContact.name,数字:hotContact === null &&正在加载HotContact?'': hotContact.number,});const onFormDataChange = (事件) =>{setFormData({ ...formData, [event.target.name]: event.target.value });};const { 名称,编号} = formData;const handleSubmit = (事件) =>{event.preventDefault();const newContact = { 姓名,号码};添加联系人(新联系人);console.log('提交表单!');setFormData({ name: '', number: '' });};const handleUpdateSubmit = (事件) =>{event.preventDefault();const updatedContact = { name, number };updateContact(hotContact._id, updatedContact);};返回 !hotContact ?(<form onSubmit={handleSubmit}><div>名称{' '}<输入类型='文本'名称='名称'值={名称}onChange={(事件)=>onFormDataChange(事件)}/>

<div>数字{' '}<输入类型='文本'名称='编号'值={数字}onChange={(事件)=>onFormDataChange(事件)}/>

<input type='submit' value='添加联系人'/></表单>) : (<form onSubmit={handleUpdateSubmit}><div>名称{' '}<输入类型='文本'名称='名称'值={名称}onChange={(事件)=>onFormDataChange(事件)}/>

<div>数字{' '}<输入类型='文本'名称='编号'值={数字}onChange={(事件)=>onFormDataChange(事件)}/>

<input type='submit' value='Apply Changes'/></表单>);};const mapStateToProps = (状态) =>({联系人:state.contacts,});导出默认连接(mapStateToProps, { addContact, updateContact })(联系表);

解决方案

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

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

const ContactForm = ({增加联系人,更新联系方式,联系人:{ hotContact, loadingHotContact },}) =>{const [formData, setFormData] = useState({名称:hotContact === null &&正在加载HotContact?'': hotContact.name,数字:hotContact === null &&正在加载HotContact?'': hotContact.number,});useEffect(() => {const {name, number} = props.hotContact;设置表格数据({姓名:姓名 ||'',号码:号码 ||'',});//执行这个}, [hotContact]);//当 hotContact 改变时}

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

const {name, number} = props.hotContact;设置表格数据({姓名:姓名 ||'',号码:号码 ||'',});

I'm building contact manager. When the user clicks the update button for a specific contact an action is dispatched and the "hotContact" property in the reducer's state is populated with an object. What I want is the fields of the ContactForm to be populated with the name and number of the "hotContact". However, despite the hotContact being loaded into the redux state my ContactForm component won't display the name and number of the hotContact. How can I proceed? This is what I have so far.

I tried calling setFormData in a conditional block to check if hotContact is present and loadingHotContact is false, but that just gives me an infinite re-render error.

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
);

解决方案

This doesn't work because at the first renderer useState is initialized with the hotContact from the props, but when you receive the new value from the props the state doesn't update (that's how the useState hook works)

If you want to update your state you should use the useEffect hook:

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
}

Also, I think you may simplify you assignment this way:

const {name, number} = props.hotContact;

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

这篇关于使用来自 Redux 状态的数据更新功能组件本地状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆