Home > database >  React preserving state even though key has changed
React preserving state even though key has changed

Time:12-28

The react component is preserving the "wasEdited" state even when the properties and key are changed. When any div element is edited from its initial value, the classname of the div row will be changed, thus showing a red border on the left side.

I was able to get around the issue by resetting the state manually every time the "globalId" property is changed. As you can see in the comment, I suspect this may be a similar issue to this:

React does not re-render updated map, even with different keys

But in my case I'm not mutating an object.

function Attribute ({globalId, name, value}) {
    const [wasEdited, setWasEdited] = useState(false);

    const handleInput = (e) => {
        e.target.innerHTML === value ? setWasEdited(false) : setWasEdited(true);
    };

    // TODO: This useEffect is a hack to reset the wasEdited state when the globalId changes. I don't understand
    // why this is necessary, since each Attribute component is rendered with a unique key. I think it
    // has something to do with this post on [stack overflow](https://stackoverflow.com/questions/68949376///react-does-not-re-render-updated-map-even-with-different-keys).
 

    // useEffect(() => {
    //     return () => setWasEdited(false);
    // }, [globalId])

    console.log(`${globalId}-${name}`, wasEdited)

    return (
        <div key={`${globalId}-${name}`} className={wasEdited ? 'row was-edited' : 'row'}>
            <div className='col'>{name}</div>
            <div className='col' onInput={handleInput} contentEditable>{value}</div>
        </div>
    )
}

This is what it looks like: This is what it looks like

CodePudding user response:

Putting a key on a div will cause that div to unmount and remount when the key changes. But it will have no effect on the component surrounding that div (Attribute). If you want to deliberately unmount and remount Attribute, you need to put a key on Attribute. So wherever you're rendering it, do:

<Attribute key={`${globalId}-${name}`} globalId={globalId} name={name} value={something} />
  • Related