为什么在组件中导入 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 循环正在修改数据,我认为不需要 useState
或 useEffect
但我可能错了。
为什么对象数组的行为与组件中导入的硬编码 VS 不同?
编辑:
这里的不同想法是 useRef
、useState
、useEffect
的尝试:
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;
尝试坚持使用硬编码数据的工作流程作为外部参考文件,以防我想依赖 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 循环正在修改数据,我认为不需要 useState
或 useEffect
但我可能错了。
为什么对象数组的行为与组件中导入的硬编码 VS 不同?
编辑:
这里的不同想法是 useRef
、useState
、useEffect
的尝试:
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;