如何在每次导入时获取导出对象的新实例?

How to get a new instance of an exported object on each import?

我有这个文件,我正在为我正在构建的表单字段保留一个 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 而不是 [] 并在消费者文件中初始化它?

Is there a way to keep an array as a initial value living declared and imported from another file and always get a new reference to it on each import?

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

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

// 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];
});

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