Использование нового состояния в функции после установки - PullRequest
0 голосов
/ 16 апреля 2020

Можно ли использовать обновленное состояние в той же функции, в которой оно было обновлено? В приведенном ниже примере я получаю 0.

При useEffect я могу получить доступ к новому состоянию сразу после установки состояния, но что, если я хочу получить доступ к функции.

Как Дополнительный вопрос, могу ли я или должен использовать состояние для ситуаций, когда оно не связано напрямую с тем, что находится в возврате? Должен ли я использовать реквизит вместо этого?

function App() {
  const [count, setCount] = useState(0)

  const handleClick = async () => {
    setCount(count => (count + 1));
    await new Promise(r => setTimeout(r, 2000));
    console.log(count); // I get 0
  }

  return (
    <div>
      <Button onClick={handleClick}></Button>
    </div>
  )
}

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Нет, вы не можете (или, может быть, вы можете с небольшой хитростью, как я покажу вам). С функциональными компонентами состояние немного отличается. Ваша функция handleClick создается при рендеринге компонента, и из-за того, как работает JavaScript, она привязывается к «области» этого конкретного рендера. Даже после истечения времени ожидания он все еще находится в той старой области действия.

Один из способов решения этой проблемы может заключаться в использовании ссылки.

function App() { 
    const [count, setCount] = useState(0)

    const countRef = useRef(count)
    countRef.current = count

    const handleClick = async () => {
        setCount(count => (count + 1)); 
        await new Promise(r => setTimeout(r, 2000)); 
        console.log(countRef.current); 
    } 

    return ( 
        <div>
            <Button onClick={handleClick}></Button>
        </div>
    )
}

Это обновит ссылку, когда компонент перезапустится. -rendered. Это обновление изменит все ссылки, даже те, что были в старых областях.

Однако я довольно часто использую React и уверен, что мне никогда не приходилось использовать это на практике. Я бы сказал, что это плохая практика: даже с тайм-аутом вы не можете быть на 100% уверены, что у штата на самом деле было достаточно времени для обновления, так что это может привести к странным ошибкам. Почему вы на самом деле хотите сделать это? Разве вы не можете вместо этого поместить свой код, который требует нового состояния, в useEffect, например?

Что касается дополнительного вопроса: вы должны использовать состояние, когда вам нужно повторно визуализировать компонент всякий раз, когда состояние изменяется. Если вы не хотите, чтобы ваш компонент повторно отображался при изменении состояния, вам следует использовать другой метод хранения данных (например, ссылки).

1 голос
/ 16 апреля 2020

Ты просто не можешь. Вот почему я использую useReducer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...