【问题标题】:React rerendering - misunderstandingReact 重新渲染 - 误解
【发布时间】:2020-08-31 14:46:33
【问题描述】:

我认为 React 只是重新加载我需要的东西 - 在我的情况下它看起来不同或者我做错了什么。

我有员工表。对于一天中的每个员工,我可以设置工作的开始和结束时间。像这样:

const ScheduleRow = React.memo((props) => {
    return (
        <tr>
            // number of row - doesn't matter
            <th className="text-center">{ props.no }</th>
            { ["2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04" /* etc */ ].map(
                date => { return (
                    <ScheduleCell date={ date } employee_id={ props.employee_id }/>
                )}) }
        </tr>
    )
})

const ScheduleCell = React.memo((props) => {
    const dispatch = useDispatch()

    let schedule_id = `${props.employee_id}:${props.date}`
    const schedule = useSelector(state => state.schedules)[schedule_id] || null

    /* some code here - not changing state */

    console.log(props.date)

    return (
        <td>
            <Form.Control type="text" value={schedule?.begin}
                onChange={(e) => dispatch({
                    type: "EDIT_SCHEDULE",
                    schedule_id: schedule_id,
                    property: "begin",
                    value: e.target.value
                })}/>
            <Form.Control type="text" value={schedule?.cease}
                onChange={(e) => dispatch({
                    type: "EDIT_SCHEDULE",
                    schedule_id: schedule_id,
                    property: "cease",
                    value: e.target.value
                })}/>
        </td>
    )
});

您可以看到我在 ScheduleCell 中有 console.log(),然后返回打印正在编辑的日期。我相信当我更改单元格(例如日期“2020-01-02”)时,我应该在控制台中只看到“2020-01-02”。但是我在 ScheduleRow 中看到数组中的每个日期,这意味着即使我只更改了一个单元格,React 也会修改每个单元格。

我的推理有什么问题,如何改进它以重新加载仅编辑单元格?

【问题讨论】:

  • 您至少在 ScheduleCell 渲染内部或行上缺少 key 道具。

标签: javascript node.js reactjs redux virtual-dom


【解决方案1】:

确保为 &lt;ScheduleCell/&gt; 元素添加正确的 key 属性。没有这个,React 不会关联相同的组件实例应该在重新渲染时重用。任何呈现 &lt;ScheduleRow/&gt; 的东西也是如此。

const ScheduleRow = React.memo((props) => {
    return (
        <tr>
            <th className="text-center">{ props.no }</th> // number of row - doesn't matter
            { ["2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04" /* etc */ ].map(date => { return (
                <ScheduleCell key={ date } date={ date } employee_id={ props.employee_id }/>
            )}) }
        </tr>
    )
})

React.memo 仅在组件实例的上下文中记忆输出,前提是 props 与该实例上次呈现的时间相同。有关其工作原理的更多信息,请阅读 React 的 Reconciliation。

【讨论】:

  • key={} 属性必须是唯一的,因此如果您的日期列表将包含 dups,请确保使用其他内容。
  • 请注意,它只需要在其父项中是唯一的;在这种情况下,我猜&lt;ScheduleRow/&gt; 元素也是使用.map(...) 之类的东西创建的;如果是这样,他们还需要唯一的密钥。例如,如果每个员工 ID 的每一行都是唯一的,那么这将是一个很好的键。如果每个时间表单元格在每个日期每个员工都是唯一的,那么 date 将是一个很好的关键,因为每个员工的唯一性已经在父级中得到处理。
  • 我为控制台告诉我更改但没有任何更改的每个组件添加了唯一键。
  • 您的密钥是唯一的,同时也是标识和一致的吗?仅使用唯一键将消除警告,但除非它也是其他两件事,否则您将无法重用组件。
  • 对于我的 ScheduleRow,我有 row-${employe_id},对于 ScheduleCell,我有 cell-${schedule_id}。够了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 2016-12-30
  • 2021-03-07
  • 2021-06-03
  • 2021-12-27
相关资源
最近更新 更多