【问题标题】:Passing setStateof nested object to child in React将嵌套对象的 setState 传递给 React 中的子对象
【发布时间】:2025-12-17 03:50:01
【问题描述】:

我有一个问题一直在谷歌上搜索,但找不到答案。如果我有一个组件(父级)的状态使用useState 钩子和另一个我想将 setState 函数传递给但状态是嵌套对象的组件(子级),我该怎么做。例如:

家长:

import React, { useState } from 'react';

import ChildComponent from '../components/ChildComponent

export default function Parent() {
const [state, setState] = useState({name: '', age: '', height: '', eyeColor: ''})
return (
     <h1>Title</h1>
     <ChildComponent state={state} setState={???}/>
);
}

孩子:

import React, { useState } from 'react';

export default function ChildComponent({state, setState}) {

return (
     <label htmlFor='nameInput'>Name:</label>
     <input name='nameInput' value={state.name} onChange={(e) => setState???}/>
);
}

我通常知道如果状态在一个组件中,您会使用setState({...state, state.name: 'Jane'}),但我不确定如何将这种setState 传递下去。

编辑:我希望 ChildComponent setState 函数是动态的,因此我可以为每个状态值(名称、年龄、身高、眼睛颜色)重复使用该组件 4 次,其中相同的组件可能会将一个值传递给更改更新什么值?

【问题讨论】:

  • 如果您似乎打算独立更新它们,为什么要将所有这些值存储在一个状态对象中?
  • 我为每个值使用了多个 setState 钩子。我只是想知道是否可以在一个状态对象中做到这一点。也许不是,在这种情况下,我将继续使用多个钩子。

标签: javascript html reactjs


【解决方案1】:

一种方法(多种可能):

export default function Parent() {
    const [state, setState] = useState({name: '', age: '', height: '', eyeColor: ''})
    const change = prop => ({target}) => setState(state => ({...state,[prop]:target.value}));

     return (
         <h1>Title</h1>
         <ChildComponent label="Name" value={state['name']} onChange={change('name')}/>
         <ChildComponent label="Age" value={state['age']} onChange={change('age')}/>
         <ChildComponent label="Eye Color" value={state['eyeColor']} onChange={change('eyeColor')}/>
     );
}

export default function ChildComponent({label,value,onChange}) {

   return (
     <label htmlFor={`${label}Input`}>{label}:</label>
     <input name={`${label}Input`} value={value} onChange={onChange}/>
   );
}


【讨论】:

    【解决方案2】:

    您可以使用setState的函数形式来访问当前状态。

    setState 作为第一个参数传递当前状态:

    onChange={(e) => setState(currentState => ({...currentState, name: newName}))}
    

    【讨论】:

    • 对不起,也许我应该更清楚,我会编辑我的帖子。我将如何使setState 动态化,以便我可以对state 中的每个值重复使用ChildComponent 4 次,即姓名、年龄、身高、眼睛颜色。从您的回答看来,ChildComponent 似乎只能更新statename 值。
    • 这只是一个如何更新name的例子。要更新状态的其他部分,请遵循相同的模式
    【解决方案3】:

    您可能会受益于使用React.createContextReact.useContext 在组件之间传递状态。

    来自文档:

    在典型的 React 应用程序中,数据通过 props 自上而下(父级到子级)传递,但这对于应用程序中许多组件所需的某些类型的 props(例如区域设置偏好、UI 主题)可能很麻烦. Context 提供了一种在组件之间共享此类值的方法,而无需通过树的每一层显式传递一个 prop。

    这是一个示例,如何使用上下文在 n 级深的组件之间共享状态。

    const {
      useState,
      useEffect, 
      createContext,
      useContext
    } = React;
    
    const ComponentContext = createContext();
    
    function Parent() { 
      const [state, setState] = useState({name: 0, age: 0});
      return ( 
        <ComponentContext.Provider value={state}>
            <div>Parent</div>
            <Child/>
            <button 
                onClick={()=>setState({...state, name: state.name+1})}>
                    Update Name
            </button>
            <button 
                onClick={()=>setState({...state, age: state.age+1})}>
                    Update Age
            </button>
        </ComponentContext.Provider>
      );
    }
    
    function Child() { 
      const {name} = useContext(ComponentContext);
      return <div>
          <div>1st Child: {name}</div>
          <Child2/>
      </div>;
    }
    
    function Child2() { 
      const {age} = useContext(ComponentContext);
      return <div>2nd Child: {age}</div>;
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render( <Parent /> , rootElement);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

      【解决方案4】:

      您可以像传递state 一样传递setState。 家长:

       import React, { useState } from 'react';
      
       import ChildComponent from '../components/ChildComponent
      
       export default function Parent() {
       const [state, setState] = useState({name: '', age: '', height: '', eyeColor: ''})
       return (
           <h1>Title</h1>
           <ChildComponent state={state} setState={setState}/>
       );
      }
      

      孩子:

       import React, { useState } from 'react';
      
       export default function ChildComponent({state, setState}) {
      
       return (
           <label htmlFor='nameInput'>Name:</label>
           <input name='nameInput' value={state.name} onChange={(e) => setState(e.target.value)}/>
       );
       }
      

      【讨论】: