【问题标题】:How to get a new instance of an exported object on each import?如何在每次导入时获取导出对象的新实例?
【发布时间】:2019-12-09 17:45:12
【问题描述】:

我有这个文件,我正在为我正在构建的表单字段保留一个 INITIAL_VALUE。

INITIAL_VALUE.js

const INITIAL_VALUE = [];

export default INITIAL_VALUE;

问题是INITIAL_VALUE 是一个数组。一个非原始的,由引用处理。

Component1.js

import INITIAL_VALUE from "./INITIAL_VALUE";
import React, { useState } from "react";

function Component1(props) {
  const [myState, setMyState] = useState(INITIAL_VALUE);
  const [boolean, setBoolean] = useState(false);

  function handleClick() {
    setMyState(prevState => {
      prevState.push(1);
      return prevState;
    });
    setBoolean(prevState => !prevState);
    props.forceUpdateApp();
  }

  return (
    <React.Fragment>
      <div>This is my state: {JSON.stringify(myState)}</div>
      <button onClick={handleClick}>Modify State Comp1</button>
    </React.Fragment>
  );
}

export default Component1;

Component2.js

The same as Component1, but it's named Component2 and it has its own file.

App.js

function App() {
  const [boolean, setBoolean] = useState(false);

  function forceUpdateApp() {
    setBoolean(prevState => !prevState);
  }

  return (
    <React.Fragment>
      <Component1 forceUpdateApp={forceUpdateApp} />
      <Component1 forceUpdateApp={forceUpdateApp} />
      <Component2 forceUpdateApp={forceUpdateApp} />
    </React.Fragment>
  );
}

CodeSandbox

问题

Component1.jsComponent2.js 都导入INITIAL_VALUE 文件。 我的印象是,这些导入中的每一个都会获得一个全新的 INITIAL_VALUE 对象实例。但事实并非如此,我们可以从下面的 GIF 中看到:

问题

有没有办法将数组作为初始值保持声明并从另一个文件导入,并始终在每次导入时获取对它的新引用?我可以用另一种模式来解决这个问题吗?还是应该只使用原始值并将其设为 null 而不是 [] 并在消费者文件中对其进行初始化?

【问题讨论】:

    标签: javascript arrays reactjs object primitive


    【解决方案1】:

    有没有办法将数组作为初始值保持声明并从另一个文件导入,并在每次导入时始终获得对它的新引用?

    不,这是不可能的。模块的最顶层代码最多会运行一次。在这里,INITIAL_VALUE.js 的顶层定义了 one 数组并将其导出,因此导入它的所有内容都将引用同一个数组。

    最简单的调整是导出一个创建数组的函数:

    // makeInitialValue.js
    export default () => {
      const INITIAL_VALUE = [];
      // the created array / object can be much more complicated, if you wish
      return INITIAL_VALUE;
    };
    

    然后

    import makeInitialValue from "./makeInitialValue";
    function Component1(props) {
      const INITIAL_VALUE = makeInitialValue();
      const [myState, setMyState] = useState(INITIAL_VALUE);
    

    在您只需要一个空数组的简化情况下,将它传递给useState 时定义它会更容易。

    话虽如此,最好修复您的代码,使其不会改变现有状态。改变

    setMyState(prevState => {
      prevState.push(1);
      return prevState;
    });
    

    setMyState(prevState => {
      return [...prevState, 1];
    });
    

    这样,即使所有组件和组件实例都从同一个数组开始,也不会造成问题,因为数组永远不会发生变异。

    【讨论】:

    • 感谢您的回答。我刚刚尝试过,但发生的情况是Component2 获得了一个新实例。但是Component1 最终都共享同一个实例。有解决办法吗?
    • 不需要调用INITIAL_VALUE函数,可以直接传递给useState,它会被延迟初始化:reactjs.org/docs/hooks-reference.html#lazy-initial-state
    • 我的真实案例我有 5 个可能的初始值,它们基于某个表单字段 type。一些类型应该有空的array,其他的会有空的string,其他的是false,等等。
    • 我的错,我在顶层调用函数。如果我在组件内部调用它,一切都很好,每个人都有自己的实例!谢谢!!
    • @cbdev420 请记住,这是一个 X/Y 问题的,对于 React 的这种特殊情况 - 最好不要在全部。每次调用 setMyState 时最好创建一个新数组
    猜你喜欢
    • 2021-10-26
    • 2023-01-29
    • 2018-10-08
    • 2017-12-12
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 2019-06-27
    • 2016-01-22
    相关资源
    最近更新 更多