首页 > 解决方案 > 如何在每次导入时获取导出对象的新实例?

问题描述

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

INITIAL_VALUE.js

const INITIAL_VALUE = [];

export default INITIAL_VALUE;

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

组件1.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;

组件2.js

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

应用程序.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>
  );
}

代码沙盒

问题

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

在此处输入图像描述

问题

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

标签: javascriptarraysreactjsobjectprimitive

解决方案


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

不,那是不可能的。模块的最顶层代码最多运行一次。在这里,顶层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];
});

这样,即使所有组件和组件实例以相同的数组开始,也不会导致问题,因为数组永远不会发生变异。


推荐阅读