使用来自 Redux 状态的数据更新功能组件本地状态
Updating Functional Component Local State Using Data From Redux State
我正在构建联系人管理器。当用户单击特定联系人的更新按钮时,将调度一个操作,并用一个对象填充 reducer 状态中的 "hotContact" 属性。我想要的是用 "hotContact" 的名称和号码填充 ContactForm 的字段。然而,尽管 hotContact 被加载到 redux 状态,但我的 ContactForm 组件不会显示 hotContact 的名称和号码。我该如何进行?这是我目前所拥有的。
我尝试在条件块中调用 setFormData 来检查 hotContact 是否存在以及 loadingHotContact 是否为 false,但这只会给我一个无限的重新渲染错误。
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
);
这不起作用,因为在第一个渲染器 useState
中使用道具中的 hotContact
进行了初始化,但是当您从道具中收到新值时,状态不会更新(这就是 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 || '',
});
我正在构建联系人管理器。当用户单击特定联系人的更新按钮时,将调度一个操作,并用一个对象填充 reducer 状态中的 "hotContact" 属性。我想要的是用 "hotContact" 的名称和号码填充 ContactForm 的字段。然而,尽管 hotContact 被加载到 redux 状态,但我的 ContactForm 组件不会显示 hotContact 的名称和号码。我该如何进行?这是我目前所拥有的。
我尝试在条件块中调用 setFormData 来检查 hotContact 是否存在以及 loadingHotContact 是否为 false,但这只会给我一个无限的重新渲染错误。
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
);
这不起作用,因为在第一个渲染器 useState
中使用道具中的 hotContact
进行了初始化,但是当您从道具中收到新值时,状态不会更新(这就是 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 || '',
});