React memo()清除钩子状态-旧数据再次出现

时间:2019-12-12 13:51:16

标签: reactjs

我正在尝试第一次使用React memo(),以防止不必要地重新呈现 TextInputs 用于 notes 。成功阻止了这些重新渲染,并且页面性能略有提高(实际示例中可能有数百个注释)。

但是,按下重置按钮后,会发生奇怪的事情。更改以前未编辑过的注释会导致旧注释重新出现在其他 TextInputs 中。

我的问题是: 为什么旧笔记会以这种方式重新出现?在保持最佳渲染效果的同时如何解决呢?

import React, { useState } from 'react';

export const ReRendering = () => {

    const defaultNotes = [
        {id: '0155', note: ''},
        {id: '0197', note: ''},
        {id: '0045', note: ''},
        {id: '0244', note: ''},
        {id: '0162', note: ''},
    ];

    const [notes, setNotes] = useState(defaultNotes);


    function updateNote(e) {

        let newNotes = [];

        notes.map(r => {
            if(e.target.name === r.id) {
                r.note = e.target.value;
            }
            newNotes.push(Object.assign(r));
        });

        setNotes(newNotes);

    }


    return (

        <div className={'mt-5'}>

            <h3>Notes</h3>

            <table className={'table table-sm'}>
                <thead>
                <tr>
                    <th>ID</th>
                    <th>Note</th>
                </tr>
                </thead>
                <tbody>
            {notes.map(note => {
                return (
                    <tr key={note.id}>
                        <td>
                            <input type={'text'}
                                   disabled
                                   className={'form-control border-0'}
                                   value={note.id}
                            />
                        </td>
                        <td>
                            <MemoTextInput
                                value={note.note}
                                name={note.id}
                                handleChange={updateNote}
                            />
                        </td>
                    </tr>
                )

            })}
            </tbody>
            </table>

            <button onClick={() => setNotes(defaultNotes)}>Revert</button>

        </div>
    )
};

const TextInput = ({value, handleChange, name}) => {

    return (
        <input
            type={'text'}
            className={'form-control'}
            value={value}
            onChange={handleChange}
            name={name}
        />
    )

};

function areEqual(prevProps, nextProps) {
    return prevProps.value === nextProps.value;
}

const MemoTextInput = React.memo(TextInput, areEqual);

2 个答案:

答案 0 :(得分:0)

分配partition by时,您正在更改原始状态(默认音符),这可能会对其他所有内容产生不良影响。

r.note = e.target.value;

答案 1 :(得分:0)

问题与updateNote()函数有关。没有重新渲染的TextInputs上有一个旧版本的 updateNote(),因此也有一个旧版本的 notes

使用updateNotes()的修订版,它可以正常工作。

function updateNote({target}){

        setNotes(oldNotes => {
            const newNotes = [...oldNotes];
            newNotes.filter(n => n.id === target.name)[0] = {...oldNotes.filter(n => n.id === target.name)[0]};
            newNotes.filter(n => n.id === target.name)[0].note = target.value;
            return newNotes;
        })
    }