【问题标题】:Organizing and setting state from another file从另一个文件组织和设置状态
【发布时间】:2021-04-26 14:15:46
【问题描述】:

我有一些数据(对象)存在于它们自己的文件(Origin.js)中。

正在使用扩展运算符在另一个名为 OriginState 的对象中导出此数据:

Origin.js

//info
const info = {
    title: '',
    year: '',
};

//images
const images = {
    logo: '',
    heroImage: '',
};

//text
const text = {
    header: '',
    body: '',
};

export const OriginState = {
    ...info,
    ...images,
    ...text,
};

我正在将我的 OriginState 对象导入到另一个文件中,并将其用作我的应用程序的 state,如下所示:

OtherFile.js

import { OriginState } from './Origin.js';

    const [state, setState] = useState({
        ...OriginState,
    });

这是一个示例处理程序,我稍后使用此状态更新输入中的某些指定状态值:

const handleChange = (e) => {
    const { name, value } = e.target;
    setState((state) => ({
        ...state,
        [name]: value,
    }));
};

现在,我的问题是……这样存储state 不正确吗?

另外,我是否在处理函数中错误地使用了setState

在大多数情况下,我见过这样声明和更新的状态,这显然更容易阅读:

const [count, setCount] = useState(0);
setCount(count + 1)

但我有很多 state,我认为拥有多个 setState 钩子不是一个好主意。

有没有更好的方法来做到这一点?我现在的感觉是不对的。

【问题讨论】:

    标签: javascript reactjs state


    【解决方案1】:

    这样存储状态不正确吗?

    const handleChange = (e) => {
        const { name, value } = e.target;
        setState((state) => ({
            ...state,
            [name]: value,
        }));
    };
    

    不,一点也不,事实上,它通常是状态更新的首选模式。

    任何时候你的状态更新依赖之前的状态,即经典的反例,或者在你的情况下,当有嵌套状态时,你应该使用函数状态更新从前一个状态更新,而不是前一个渲染周期的状态。

    另外,我是否在处理函数中错误地使用了 setState?

    在大多数情况下,我看到状态声明和更新是这样的 显然更容易阅读:

    const [count, setCount] = useState(0);
    setCount(count + 1)
    

    我认为处理程序中的状态更新逻辑没有问题。在这个count 示例中,更新这样的计数(应该)被认为是不正确的。请参阅此代码框演示,该演示试图显示非功能状态更新和功能状态更新之间的问题。

    正确的状态更新应该是setCount(count => count + 1)

    但我有很多状态,不认为这是一个好主意 有多个 setState 钩子。

    有没有更好的方法来做到这一点?我现在的感觉 错了。

    当谈到表单输入和状态时,我认为拥有一个平面对象是有意义的。虽然在使用具有“复杂”状态形状的单个 useState 钩子或为每个“块”状态使用单个 useState 钩子时,通常没有真正的正确或错误答案。这是一个固执己见的答案,主要针对特定​​用例做有意义的事情。

    虽然我会说如果一组值甚至是松散相关的,那么将它们存储在一个公共对象中也许是有意义的,但这是我的意见。

    我看到您导入的数据的一个潜在问题是您可能会通过使用 Spread 语法无意中覆盖某些键值对。

    export const OriginState = {
        ...info,
        ...images, // <-- could overwrite values from info
        ...text, // <-- could overwrite values from info and images
    };
    

    【讨论】:

    • 感谢您的全面回答,我非常感谢沙盒示例,因为它确实为我解决了一些问题。 - 我看到其他人使用useCallback 钩子来防止重新渲染,功能状态更新是否可以作为替代方案? - 另外,对于传播的潜在问题,解决方法是什么?我应该单独导出这些对象吗?
    • useCallback 解决了另一个问题。它只是简单地记忆一个函数,因此您可以为子组件提供稳定的回调引用,并且回调 prop 值不会在渲染之间更改,除非回调的依赖项之一更新。不,传播很好,只是你应该知道如果你定义了重复的键,那么后面的传播将覆盖第一个。如果您还导出每个“块”,那么您稍后可以使用更多选项来合并这些对象。
    【解决方案2】:

    您的方法似乎很合法,这是最佳实践之一,如果您的newState 依赖于oldState,则使用setState callback 并从callback input 获取旧状态,否则如上所示,如果你可以这样使用它:

    const [count, setCount] = useState(0);
    setCount(count + 1)
    

    您可能会增加获得stale data 的机会,这将增加出现错误的可能性

    【讨论】:

    • 感谢您的回答。 - 再次确认这没关系。话虽如此,我想我的问题是我的OtherFile.js 中有多个处理函数。我将这些函数连同来自Origin.jsstate 一起发送到多个组件。它看起来很乱,因为其中一些组件有超过 20 个道具。我担心会出现无法控制的情况。
    • state 本身并非来自Origin.js,它只是来自Origin.js 文件的state 的默认值。如果您有多个使用相同默认状态的地方,最好将它们存储在单独的文件中,例如Origin.js,而不是将其复制粘贴到所有这些地方@AibCodesDaily
    • 感谢您的帮助!感谢您确认我的疑问并增加我的知识。我不久前启动了这个应用程序,忘记了为什么我会以这种方式做一些事情。确认将帮助我继续前进。
    • @AibCodesDaily 很高兴我能帮上忙。干杯
    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 2018-03-19
    • 2020-10-03
    • 2018-10-30
    • 2019-12-11
    • 2021-10-18
    • 2016-10-14
    • 1970-01-01
    相关资源
    最近更新 更多