Как сбросить состояние компонента React самостоятельно

Как сбросить состояние компонента React самостоятельно

Состояние компонента react (определяемое useState) остается неизменным во время рендеринга и изменяется только при ручном изменении. Одним из распространенных способов сбросить состояние является их ручное изменение:

const Demo = () => {
const [name, setName] = useState('default');
const [address, setAddress] = useState(null);

const reset = () => {
setName('default');
setAddress(null);
}

return (
...
<button onClick={()=>reset()} >Сброс</button>
);
}

Это не идеальный вариант по трем причинам:

  1. Начальное состояние повторяется, и нам может понадобиться извлечь его в другую переменную, чтобы предотвратить несовпадение ошибок
  2. Необходимо синхронизировать оба состояния при обновлении
  3. Если состояние добавляется из пользовательского хука, у нас нет возможности сбросить его непосредственно из компонента

Лучший способ - сбросить состояние, добавив специальный параметр key. Хорошо известно, что нам нужно передавать key при отображении списка компонентов. Но его также можно использовать для сброса состояния компонента. Но это подразумевает добавление нового состояния в родительский компонент только для сброса состояния дочернего компонента.

  const Demo = ({reset}: {reset:()=>void})=>{
    const [name, setName] = useState('default');
    const [address, setAddress] = useState(null);

    return (
      <button onClick={()=>reset()}>Reset</button>
    );
  }

  const Parent = ()=>{
    const [resetKey, setResetKey] = useState(0);

    return (
      ...
      <Demo key={resetKey} onReset={ ()=> setResetKey(resetKey+1)} />
    )
  }

Здесь мы принудительно изменяем значение свойства key, которое сбрасывает состояние компонента вручную. Технически он делает это не сам, а с помощью родительского компонента, но это, кажется, самый чистый способ сброса.
Недостатком этого способа является перерисовка родительского компонента и всех его дочерних компонентов. Но поскольку никакое другое состояние не изменяется, в идеале это не должно быть большой проблемой.

Codesandbox для игры с :