Как правильно получить состояние react fresh перед рендерингом компонента?

#reactjs #react-state-management

#reactjs #реагирование-управление состоянием

Вопрос:

Прошу прощения, если ответ очевиден. Вероятно, я пропустил шаблон для этого…

У меня есть такая архитектура (конечно, более сложная): компонент (здесь кнопка) должен вызывать функцию и устанавливать состояние одновременно.

Конечно, этот пример не работает, потому что отображаемое состояние word не определено до speak() вызова функции.

Каков наилучший способ сделать это?

 const Speaker = () => {
  const [word, setWord]=  useState ("nothing")

  const speak = () => {
    console.log(word)
    ...
  }

  const speakDirectly = () => {
    setWord("hello")
    speak() // say "nothing" instead of "hello" 😞
  }

  const prepareWord = (wordToPrepare) => {
    setWord(wordToPrepare)
  }

  return (
    <>
    <p>Thinking word : {word} </p>
    <button onClick={() =>prepareWord('Goodbye')} >Prepare to say "Goodbye"</button>
    <button onClick={() =>prepareWord('Goodnight')} >Prepare to say "Goodnight"</button>
    ----
    <button onClick={() =>speak()} >Say Hello</button> 
    <button onClick={() =>speakDirectly('hello')} >Say Hello</button> 
    </>
  )

}
 

Существует ли шаблон для разрешения этого поведения в React?

Я хочу избежать обновления моих функций подобным образом 🤢

 const Speaker = () => {
  const [word, setWord]=  useState ("nothing")

  const speak = (directWord) => {
        let wordToSay = directWord || word
        console.log(word)
        ...
   }
   const speakDirectly = (directWord) => {
        setWord(directWord)
        speak(directWord) 
   }
    ...
 

Комментарии:

1. setWord() вот асинхронный.

2. Да, тогда это невозможно? Мне абсолютно необходимо иметь разделенную логику между этими компонентами?

3. Не невозможно.

4. да, это подтверждает то, что я думал… Большое вам спасибо

5. Вы можете использовать эффект, чтобы обойти вашу проблему.

Ответ №1:

Вы могли бы сделать что-то вроде этого. Укажите состояние для вашего word и вашего прямого word. Используйте эффект для вашего прямого слова, чтобы запускать speak всякий раз, когда оно обновляется, но вызывайте speak по щелчку для вашего готового слова.

 const Speaker = () => {
  const [preparedWord, setPreparedWord]=  useState();
  const [directWord, setDirectWord]=  useState();

  const speak = (word) => {
    console.log(word)
    ...
  }

  useEffect(() => directWord amp;amp; speak(directWord), [directWord]);

  return (
    <>
    <p>Thinking word : {preparedWord} </p>
    <button onClick={() => setPreparedWord('Goodbye')} >Prepare to say "Goodbye"</button>
    <button onClick={() => setPreparedWord('Goodnight')} >Prepare to say "Goodnight"</button>
    ----
    <button onClick={() => speak(preparedWord)} >Speak</button> 
    <button onClick={() => setDirectWord('hello')} >Say Hello</button> 
    </>
  )

}
 

Обновить

Подумав об этом секунду, если вам не нужно, чтобы прямое слово было в вашем состоянии, вы также можете избавиться от этой части и просто вызвать speak для нее, передавая ее функции.

 const Speaker = () => {
  const [preparedWord, setPreparedWord]=  useState();

  const speak = (word) => {
    console.log(word)
    ...
  }

  return (
    <>
    <p>Thinking word : {preparedWord} </p>
    <button onClick={() => setPreparedWord('Goodbye')} >Prepare to say "Goodbye"</button>
    <button onClick={() => setPreparedWord('Goodnight')} >Prepare to say "Goodnight"</button>
    ----
    <button onClick={() => speak(preparedWord)} >Speak</button> 
    <button onClick={() => speak('hello')} >Say Hello</button> 
    </>
  )

}