为啥在组件中导入 VS 硬编码时,对象数组的行为会有所不同?
Posted
技术标签:
【中文标题】为啥在组件中导入 VS 硬编码时,对象数组的行为会有所不同?【英文标题】:Why does an array of objects behave differently when imported VS hard coded in a component?为什么在组件中导入 VS 硬编码时,对象数组的行为会有所不同? 【发布时间】:2021-12-25 14:04:49 【问题描述】:尝试坚持使用硬编码数据的工作流程作为外部参考文件,以防我想依赖像 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:
【问题讨论】:
【参考方案1】:在您重写的组件中,您将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;
【讨论】:
存在同样的问题。如果我能找到时间,我将使用代码框进行更新。仅供参考,expenses
是已在父组件中过滤的数组。所以我想我可能不得不使用useState
和useEffect
。
添加了沙箱并再次尝试。
哦,所以并不是组件被安装在其他地方,或者被卸载并重新安装,而是在同一次安装期间年份会发生变化,您希望这会导致呈现的变化。您肯定需要状态 - 当年份发生变化时,取 empty 数组并根据需要填充它,并将其设置为新状态。
是的,我认为这是最好的,但由于某种原因,当我尝试时,我一直遇到错误。我认为 useRef 会起作用,但事实并非如此,我很难过。
其中一个问题是您对数据进行了太多拆分 - 最好只有 一个 源,然后将其传递。由于您希望显示依赖于数组中的内容,因此数组应该处于状态,而不是参考。以上是关于为啥在组件中导入 VS 硬编码时,对象数组的行为会有所不同?的主要内容,如果未能解决你的问题,请参考以下文章
在 Next/React 组件中导入 global vs getStaticProps
为啥我不能在 react native 中导入我的自定义组件
为啥 VS Code 无法在我的程序中导入 timeit 模块?