如何使用反应挂钩设置多个状态

时间:2020-06-03 23:24:46

标签: javascript reactjs react-hooks setstate

我在我的一个反应组件中设置多个状态时遇到问题。我的最终目标是:首先要设置“ casesData”状态(见下文),以便在每个后续单击事件中将“ selected”的值设置为“ true”或“ false”。然后,我想通过“ casesData”进行映射以找到“ selected:true”的位置,然后将“ case”的值添加到“ chosenCases”。因此,最后,“ chosenCases”可能看起来像:['case1','case2'],只要它们在'casesData'中的相应对象等于'selected:true'。

我的初始状态是这样设置的:

const [chosenCases, setChosenCases] = useState([]);
const [casesData, setCasesData] = useState([
    {
        case: 'Case1',
        description: 'some description',
        selected: false,
    },
    {
        case: 'Case2',
        description: 'some description',
        selected: false,
    },
]);

我通过“ casesData”状态映射将内容呈现到屏幕上。然后,我从onClick调用一个函数以开始更新状态:

return (
    <>
       {casesData.map(
           (
               casex  // casex because 'case' is a reserved word
           ) => {
               return (
                   <span
                       onClick={selectCase}
                       data-case={casex.case}
                   >
                       <p>{casex.case}</p>
                       <p>{casex.description}</p>
                   </span>
                );
           }
       )}
    </>
);

这是应该更新我两个状态的函数。

const selectCase = (event) => {
    console.log(event.target.getAttribute('data-case'));  // e.g. 'case2'

    setCasesData(
        [...casesData].map((object) => {
            if (
                object.case.toLowerCase() ===
                event.target.getAttribute('data-case').toLowerCase()
            ) {
                return {
                    ...object,
                    selected: !object.selected,
                };
            } else return object;
        })
    );

    let newArray = [];
    casesData.map((object) => {
        if (object.selected === true) {
            newArray.push(object.case.toLowerCase());
        }
    });
    setChosenCases(newArray);
};

如果运行上述功能后将状态记录到控制台,我会看到'casesData'得到正确更新,但是'chosenCases'总是落后一步。例如,“ chosenCases”在函数的第一次运行时保持为空,但在第二次运行时被设置(例如['case2'],但数据将反映先前的函数调用)。

任何帮助将不胜感激。我想知道最合适的设置方法。

1 个答案:

答案 0 :(得分:0)

最简单的方法是将新的casesData存储在变量中,这样您就不必等待新的渲染即可看到新状态:

const selectCase = (event) => {
    console.log(event.target.getAttribute('data-case'));  // e.g. 'case2'

    const newCasesData = casesData.map((object) => 
        (object.case.toLowerCase() === event.target.getAttribute('data-case').toLowerCase())
            ? {
                ...object,
                selected: !object.selected,
            } 
            : object
    )

    setCasesData(newCasesData);

    setChosenCases(
        newCasesData
            .filter(obj => obj.selected)
            .map(obj => obj.case.toLowerCase())
    );
};

您可能还想重新考虑是否需要诸如chosenCases之类的派生状态,并且只需要在渲染时弄清楚选定的情况即可。这将使您的代码更易于推理,因为您不必担心两个状态的配置。