为什么在组件中导入 VS 硬编码时对象数组的行为不同?

Why does an array of objects behave differently when imported VS hard coded in a component?

尝试坚持使用硬编码数据的工作流程作为外部参考文件,以防我想依赖 API 等外部资源。鉴于当前的工作组件:

const ExpensesChart = ({ expenses }) => {
  const chartDataPoints = [
    { label: 'Jan', value: 0 },
    { label: 'Feb', value: 0 },
    { label: 'Mar', value: 0 },
    { label: 'Apr', value: 0 },
    { label: 'May', value: 0 },
    { label: 'Jun', value: 0 },
    { label: 'Jul', value: 0 },
    { label: 'Aug', value: 0 },
    { label: 'Sep', value: 0 },
    { label: 'Oct', value: 0 },
    { label: 'Nov', value: 0 },
    { label: 'Dec', value: 0 },
  ]

  for (const expense of expenses) {
    const expenseMonth = expense.date.getMonth()
    chartDataPoints[expenseMonth].value += expense.amount
  }

  return <Child dataPoints={chartDataPoints} />
}

export default ExpensesChart

工作没有问题。当我获取对象数组 chartDataPoints 并将其隔离为文件引用并导入文件时,当数据向下传递到 Child:

时,结果会有所不同

chartData.js:

const chartDataPoints = [
  { label: 'Jan', value: 0 },
  { label: 'Feb', value: 0 },
  { label: 'Mar', value: 0 },
  { label: 'Apr', value: 0 },
  { label: 'May', value: 0 },
  { label: 'Jun', value: 0 },
  { label: 'Jul', value: 0 },
  { label: 'Aug', value: 0 },
  { label: 'Sep', value: 0 },
  { label: 'Oct', value: 0 },
  { label: 'Nov', value: 0 },
  { label: 'Dec', value: 0 },
]

export default chartDataPoints

重写组件:

// Data
import chartDataPoints from '../../data/chartData'

const ExpensesChart = ({ expenses }) => {
  for (const expense of expenses) {
    const expenseMonth = expense.date.getMonth()
    chartDataPoints[expenseMonth].value += expense.amount
  }

  return <Child dataPoints={chartDataPoints} />
}

export default ExpensesChart

我不明白为什么或者我应该说不理解为什么行为不同。我假设当道具不同时,整个组件应该在那里重新渲染 - 因为 for 循环应该重新 运行 但后者方法数据永远不会改变。如果 for 循环正在修改数据,我认为不需要 useStateuseEffect 但我可能错了。

为什么对象数组的行为与组件中导入的硬编码 VS 不同?


编辑:

这里的不同想法是 useRefuseStateuseEffect 的尝试:

const ExpensesChart = ({ expenses }) => {
  const data = useRef(chartData)
  const [chartPoints, setChartPoints] = useState(data.current)

  useEffect(() => {
    if (expenses.length === 0) return setChartPoints(data.current)

    for (const expense of expenses) {
      data.current[expense.date.getMonth()].value += expense.amount
    }
    return setChartPoints(data.current)
  }, [expenses])

  return <Chart dataPoints={chartPoints} />
}

export default ExpensesChart

但我仍然 运行 遇到问题。还包括一个 CodeSandBox:

在您重写的组件中,您将 expenses 作为道具 传递下来并对其进行变异 。突变不应该在 React 中完成,它在这里给你带来了问题——当你改变一年的费用,然后组件由于年份的变化而重新渲染时,你传递了 与之前相同的变异数组,因此更改仍然存在。

当年份改变时,从初始空数组初始化新图表数据,并避免改变初始数组:

const ExpensesChart = ({ expenses }) => {
  const [data, setData] = useState(chartData);
  useEffect(() => {
    // Expenses just changed, so set the state
    // restarting from an empty chartData array
    const newData = chartData.map(obj => ({ ...obj }))
    for (const expense of expenses) {
      newData[expense.date.getMonth()].value += expense.amount;
    }
    setData(newData);
  }, [expenses]);
  return <Child { ... {data} } />;
};

export default ExpensesChart;