React父组件异步传值给子组件收到空对象如何解决?
问题原因
- 子组件状态初始化时机错误:子组件
Team中的name状态仅在首次渲染时从props.data.name取值,此时父组件的异步请求还未返回,teamAData/teamBData初始是空对象,因此name初始值为undefined。而useState的初始值仅会在组件首次渲染时执行一次,后续父组件更新props.data也不会同步更新子组件的name状态。 - 父组件状态冗余:父组件同时维护了
teamAData.name和单独的teamAName两个重复的队名状态,用户修改队名时仅更新了teamAName,没有同步更新teamAData,导致传递给子组件的data属性永远停留在异步请求返回的初始值。 - 你看到的打印为空大概率是仅看到了首次渲染的打印结果:异步请求返回后父组件会触发重渲染,子组件也会跟着重渲染,此时第二次打印的
props.data就会有值,你可以检查控制台是否有两次打印输出。 - 额外bug:父组件第一行
const [id, setId] = props.match.params.id;写法错误,useState返回值是数组,需要改为const [id, setId] = useState(props.match.params.id);
解决方法
方案1:简化状态,去掉冗余(推荐)
父组件删掉单独的teamAName、teamBName状态,队名统一从teamAData/teamBData中取值,修改handleNameChange逻辑同步更新teamAData:
// 父组件删除这两行 // const [teamAName, setTeamAName] = useState(''); // const [teamBName, setTeamBName] = useState(''); // 修改handleNameChange function handleNameChange(teamId, name) { if (teamId == 'A') setTeamAData(prev => ({...prev, name})); else setTeamBData(prev => ({...prev, name})); }
子组件不单独维护name本地状态,直接使用props.data.name:
// 子组件删除这行 // const [name, setName] = useState(props.data.name); // 修改input和handleNameChange function handleNameChange(event) { event.preventDefault(); props.onNameChange(props.id, event.target.value); } <input type="text" value={props.data.name || ''} onChange={handleNameChange} className="input" placeholder={placeholderName} />
方案2:子组件监听props变化同步本地状态
如果需要保留子组件的本地name状态,新增useEffect监听props.data变化,主动更新本地状态:
// 子组件新增useEffect useEffect(() => { setName(props.data.name || '') }, [props.data])
内容的提问来源于stack exchange,提问作者Ruben
相关产品推荐
相关产品推荐

