React Context返回undefined:子组件状态无法传递至父组件
问题原因分析
你遇到的核心问题是混淆了React Context的传递方向:
- Context的设计是用来向下传递数据(从父组件到子/孙组件),而不是向上传递给父组件。
- 你在
Form组件内部包裹了peopleContext.Provider,这意味着只有Form组件内部的子组件才能访问到Context的值;而父组件LowerStateChallenge是Form的渲染者,不在Provider的覆盖范围内,所以调用useContext(peopleContext)会返回Context的默认值(undefined,因为createContext()没传入默认值)。
解决方案
根据你的需求,有两种常用的处理方式:
方式1:状态提升到父组件(推荐)
把people状态移到父组件LowerStateChallenge中,通过Props将修改状态的方法传递给Form,同时用Context包裹子组件实现数据向下传递:
修改后的Form组件
import { useState } from "react"; export default function Form({ onAddPerson }) { const [name, setName] = useState(""); const handleSubmit = (e) => { e.preventDefault(); if (!name) { alert("Please Provide Name Value"); return; } onAddPerson(name); setName(""); }; return ( <section> <form className="form" onSubmit={handleSubmit}> <div className="form-row"> <label htmlFor="name" className="form-label"> name </label> <input type="text" name="name" id="name" className="form-input" value={name} onChange={(e) => setName(e.target.value)} /> </div> <button className="btn btn-block" type="submit"> submit </button> </form> </section> ); }
修改后的父组件LowerStateChallenge
import React, { useState, createContext } from 'react'; import List from './List'; import Form from './Form'; import { data } from '../../../../data'; export const PeopleContext = createContext(); const LowerStateChallenge = () => { const [people, setPeople] = useState(data); const addPerson = (name) => { const fakeId = Date.now(); const newPerson = { id: fakeId, name }; setPeople([...people, newPerson]); }; // 父组件可直接访问people状态 console.log(people); return ( <PeopleContext.Provider value={{ people }}> <section> <Form onAddPerson={addPerson} /> <List people={people} /> </section> </PeopleContext.Provider> ); }; export default LowerStateChallenge;
方式2:通过回调Props向上传递状态
如果坚持要在Form组件内保留people状态,可以通过回调函数将状态传递给父组件:
修改后的Form组件
import { useState } from "react"; import { data } from "../../../../data"; export default function Form({ onPeopleChange }) { const [people, setPeople] = useState(data); const [name, setName] = useState(""); const handleSubmit = (e) => { e.preventDefault(); if (!name) { alert("Please Provide Name Value"); return; } addPerson(); setName(""); }; const addPerson = () => { const fakeId = Date.now(); const newPerson = { id: fakeId, name }; const newPeople = [...people, newPerson]; setPeople(newPeople); // 调用回调,将新状态传递给父组件 onPeopleChange(newPeople); }; return ( <section> <form className="form" onSubmit={handleSubmit}> <div className="form-row"> <label htmlFor="name" className="form-label"> name </label> <input type="text" name="name" id="name" className="form-input" value={name} onChange={(e) => setName(e.target.value)} /> </div> <button className="btn btn-block" type="submit"> submit </button> </form> </section> ); }
修改后的父组件LowerStateChallenge
import React, { useState } from 'react'; import List from './List'; import Form from './Form'; const LowerStateChallenge = () => { const [people, setPeople] = useState([]); return ( <section> <Form onPeopleChange={setPeople} /> <List people={people} /> </section> ); }; export default LowerStateChallenge;
内容的提问来源于stack exchange,提问作者Sreerag Sathyan
相关产品推荐
相关产品推荐

