在嵌套对象中,在React with Hooks中更新状态的正确方法是什么?

export Example = () => {
  const [exampleState, setExampleState] = useState(
  {masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b"
           fieldTwoTwo: "c"
           }
        }
   })

如何使用setExampleState将exampleState更新为a(附加字段)?

const a = {
masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b",
           fieldTwoTwo: "c"
           }
        },
  masterField2: {
        fieldOne: "c",
        fieldTwo: {
           fieldTwoOne: "d",
           fieldTwoTwo: "e"
           }
        },
   }
}

b(改变值)?

const b = {masterField: {
        fieldOne: "e",
        fieldTwo: {
           fieldTwoOne: "f"
           fieldTwoTwo: "g"
           }
        }
   })

当前回答

如果你使用布尔值和数组,这可以帮助你:

const [checkedOrders, setCheckedOrders] = useState<Record<string, TEntity>>({});

const handleToggleCheck = (entity: TEntity) => {
  const _checkedOrders = { ...checkedOrders };
  const isChecked = entity.id in checkedOrders;

  if (isChecked) {
    delete _checkedOrders[entity.id];
  } else {
    _checkedOrders[entity.id] = entity;
  }

  setCheckedOrders(_checkedOrders);
};

其他回答

我给您留下了一个实用函数来不可变地更新对象

/**
 * Inmutable update object
 * @param  {Object} oldObject     Object to update
 * @param  {Object} updatedValues Object with new values
 * @return {Object}               New Object with updated values
 */
export const updateObject = (oldObject, updatedValues) => {
  return {
    ...oldObject,
    ...updatedValues
  };
};

你可以这样用

const MyComponent = props => {

  const [orderForm, setOrderForm] = useState({
    specialities: {
      elementType: "select",
      elementConfig: {
        options: [],
        label: "Specialities"
      },
      touched: false
    }
  });


// I want to update the options list, to fill a select element

  // ---------- Update with fetched elements ---------- //

  const updateSpecialitiesData = data => {
    // Inmutably update elementConfig object. i.e label field is not modified
    const updatedOptions = updateObject(
      orderForm[formElementKey]["elementConfig"],
      {
        options: data
      }
    );
    // Inmutably update the relevant element.
    const updatedFormElement = updateObject(orderForm[formElementKey], {
      touched: true,
      elementConfig: updatedOptions
    });
    // Inmutably update the relevant element in the state.
    const orderFormUpdated = updateObject(orderForm, {
      [formElementKey]: updatedFormElement
    });
    setOrderForm(orderFormUpdated);
  };

  useEffect(() => {
      // some code to fetch data
      updateSpecialitiesData.current("specialities",fetchedData);
  }, [updateSpecialitiesData]);

// More component code
}

如果没有,您可以在这里找到更多实用程序:https://es.reactjs.org/docs/update.html

我已经给出了两个追加,整个对象更新,具体的关键更新的解决方案的例子

追加和修改都可以通过一个简单的步骤来完成。我认为这是更稳定和安全的,没有不可变或可变的依赖。

这就是追加新对象的方法

setExampleState(prevState => ({
    ...prevState,
    masterField2: {
        fieldOne: "c",
        fieldTwo: {
            fieldTwoOne: "d",
            fieldTwoTwo: "e"
        }
    },
}))

假设您想再次修改masterField2对象。可能有两种情况。您想要更新整个对象或更新对象的特定键。

更新整个对象-这里masterField2键的整个值将被更新。

setExampleState(prevState => ({
    ...prevState,
    masterField2: {
        fieldOne: "c",
        fieldTwo: {
            fieldTwoOne: "d",
            fieldTwoTwo: "e"
        }
    },
}))

但是如果你只想改变masterField2对象中的fieldTwoOne键呢?你可以这样做。

let oldMasterField2 = exampleState.masterField2
oldMasterField2.fieldTwo.fieldTwoOne = 'changed';
setExampleState(prevState => ({
    ...prevState,
    masterField2: oldMasterField2
}))

您必须使用Rest参数和扩展语法(https://javascript.info/rest-parameters-spread),并设置一个以preState作为setState参数的函数。

不起作用(功能缺失)

[state, setState] = useState({})
const key = 'foo';
const value = 'bar';
setState({
  ...state,
  [key]: value
});

确实工作!

[state, setState] = useState({})
const key = 'foo';
const value = 'bar';
setState(prevState => ({
  ...prevState,
  [key]: value
}));

你想要创建状态的对象

let teams = {
  team: [
    {
      name: "one",
      id: "1"
    },
  ]
}

使团队的状态为对象

const [state, setState] = useState(teams);

像这样更新状态

setState((prevState)=>({...prevState,team:[
     ...prevState.team,
     {
     name: "two",
      id: "2"
     }
]}))

更新后状态变为

{
  team: [
    {
      name: "one",
      id: "1"
    },
    {
      name: "two",
      id: "2"
    }
  ]
}

要渲染项目根据当前状态使用地图功能

{state.team.map((curr_team) => {
      return (
        <div>
           <p>{curr_team.id}</p>
           <p>{curr_team.name}</p>
        </div>
      )
})}

谢谢Philip,这帮助了我-我的用例是我有一个有很多输入字段的表单,所以我保持初始状态为对象,我不能更新对象状态。上面的帖子帮助了我:)

const [projectGroupDetails, setProjectGroupDetails] = useState({
    "projectGroupId": "",
    "projectGroup": "DDD",
    "project-id": "",
    "appd-ui": "",
    "appd-node": ""    
});

const inputGroupChangeHandler = (event) => {
    setProjectGroupDetails((prevState) => ({
       ...prevState,
       [event.target.id]: event.target.value
    }));
}

<Input 
    id="projectGroupId" 
    labelText="Project Group Id" 
    value={projectGroupDetails.projectGroupId} 
    onChange={inputGroupChangeHandler} 
/>