【问题标题】:How to change only a part of the state from child component react hooks如何从子组件反应钩子中仅更改部分状态
【发布时间】:2020-12-11 10:38:51
【问题描述】:

我的父组件拥有这样的状态

 const [formData,setFormData]=useState({
        Basics:{
            job_title:'',
            job_type:null,
            ppo:true,
            emp_type:null,
            start_date_month:null,
            start_date_year:null,
            end_date_month:null,
            end_date_year:null
        },
        Details:{},
        Preferences:{},
        Colleges:{}
    })

我将整个状态的Basics 对象作为道具传递给子组件。但是,我只希望子组件能够更改 Basics 对象而不是整个状态,如果我直接通过 setFormData 是不可能的

<Basics state={formData.Basics} setState={setFormData}/>

有没有办法我可以只将setFormData 的一部分传递给孩子,这样它就不能修改formData 的其他属性?

【问题讨论】:

  • 这就是为什么你需要使用传播对象来只更新你想要的状态。 ``` {...formData,Basics:yourNewData} ``` 一般来说好的经验法则你有很多状态。为此使用 useReducer
  • 谢谢,这就是我现在正在做的事情!你能提供一个如何使用 useReducer 的例子吗?
  • 使用 useReducer 功能更新

标签: javascript reactjs react-hooks use-state react-state


【解决方案1】:

当然。这里使用Reducer的例子:

import React from 'react';

const intialList = {
        Basics:{
            job_title:'',
            job_type:null,
            ppo:true,
            emp_type:null,
            start_date_month:null,
            start_date_year:null,
            end_date_month:null,
            end_date_year:null
        },
        Details:{},
        Preferences:{},
        Colleges:{}
    }
const formReducer = (state,action) => {
    switch (action.type) {
    case 'UPDATE_BASICS':
      return {...state,Basics:{
        ...state.Basics,...action.data
      }};
    case 'UNDO_TODO':
      return state.map(todo => {
        if (todo.id === action.id) {
          return { ...todo, complete: false };
        } else {
          return todo;
        }
      });
    default:
      return state;
  }
}

const App = () => {
  const [form, dispatch] = React.useReducer(
    formReducer,
    intialList
  );

  const updateBasicsInfo = _ => {
    dispatch({
      type: "UPDATE_BASICS",
      //You can set your form object its just dummy data
      data: {
            job_title:'Test' + Math.random(),
            job_type:"test",
            ppo:true,
            emp_type:"test",
            start_date_month:"test",
            start_date_year:null,
            end_date_month:null,
            end_date_year:null
        },
    });
  };

  return <>
  <div>
    Current job tiltle:{form.Basics.job_title}
  </div>
  //just dummy functionality to use reducer
  <button onClick={updateBasicsInfo}>
    Update job detail
  </button>
  </>
}

export default App;

这里是演示:https://stackblitz.com/edit/react-nfvktg

注意:它只更新基本字段,不会更新任何其他字段!

【讨论】:

  • 一个简单的任务有很多样板,但是这是工作,非常感谢! :)
  • 是的,同意。但是对于很多州来说,reducer 是有意义的。在较小的项目中它没有意义,但在较大的项目中它是有意义的(随着您的状态对象越来越大)
【解决方案2】:

您可以创建一个仅更新该部分的单独函数,并传递该函数而不是 setFormData:

const setBasics = value => setFormData({
  ...formData,
  Basics: value
});

<Basics state={formData.Basics} setState={setBasics} />

您可以通过将要更新的属性作为参数传递来进一步概括这个想法:

const updateSection = (section, value) => setFormData({
  ...formData,
  [section]: value
});

<Basics
  state={formData.Basics}
  setState={(value) => updateSection('Basics', value)}
/>

【讨论】:

    猜你喜欢
    • 2019-09-17
    • 2020-03-10
    • 2021-05-19
    • 1970-01-01
    • 2022-07-11
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 2020-07-12
    相关资源
    最近更新 更多