为什么我的 useEffect 在第一次渲染时不是 运行?

Why is my useEffect not running on first render?

所以我试图打乱一个句子或字符串并将单词推入一个数组以便稍后加入它们并输出这个打乱的句子但是由于某种原因 useEffect 在第一次渲染时甚至没有 运行ning使用一个空数组,但是当我更改一行并再次 运行 它时,它 运行 是预期的。我只是想知道我是否做错了什么以及如何更改它以便它在第一次渲染时 运行。

const ScrambleSentence = ({sentence}) => {
    const [words, setWords] = useState([]);
    const [scrambledSentence, setScrambledSentence] = useState('');
    let scrambledWord = [];


    function scrambleWord(n){
        var text = n.split('');
        for(var i = text.length - 1; i > 0; i--){
            var j = Math.floor(Math.random() * (i + 1));
            var temp = text[i];
            text[i] = text[j];
            text [j] = temp;
        }
        return text.join('');
    }

    useEffect(() => {
        setWords(sentence.split(' '));


        words.map(word =>{
          if(word.length <= 2){
            scrambledWord.push(word);

          }
          else{
            scrambledWord.push(scrambleWord(word));
          }
        })
        setScrambledSentence(scrambledWord.join(' '));
      }, [])


      console.log(scrambledSentence);
    return (
        <div>
            <p id='scrambled-word'>{scrambledSentence}</p>
        </div>
    )
};

export default ScrambleSentence;

效果不会 运行 渲染期间。

效果函数的第一次执行将由第一次渲染触发。

下面的代码将不起作用,因为 map 需要 return 语句,所以它是未定义的,useEffect 将控制空数组作为状态中的定义。您也不应该在渲染组件中使用 let,因为它总是会启动,为此可以使用 useRef。另外,如果您的组件包含js代码,最好将其制作成辅助文件并使用它,这样可以节省并提高性能。

 words.map(word =>{
              if(word.length <= 2){
                scrambledWord.push(word);
    
              }
              else{
                scrambledWord.push(scrambleWord(word));
              }
            })

useEffect 在第一次渲染后被调用,但是您的代码中的问题是单词状态没有在您认为更新时更新。

useEffect(() => {
        setWords(sentence.split(' ')); 
// Here you set the words state that will trigger a new render. However the words variable is empty won't be changed until the next render


        words.map(word =>{ //Here you call map on an empty array.
          if(word.length <= 2){
            scrambledWord.push(word);

          }
          else{
            scrambledWord.push(scrambleWord(word));
          }
        })

        setScrambledSentence(scrambledWord.join(' ')); 
        //Here you set the state on an empty string
      }, [])
// the useEffect doesn't run a second time because it has no dependencies.

此代码应该有效:

    const ScrambleSentence = ({sentence}) => {
    const [scrambledSentence, setScrambledSentence] = useState('');


    function scrambleWord(n){
        var text = n.split('');
        for(var i = text.length - 1; i > 0; i--){
            var j = Math.floor(Math.random() * (i + 1));
            var temp = text[i];
            text[i] = text[j];
            text [j] = temp;
        }
        return text.join('');
    }

    useEffect(() => {
        let scrambledWord = [];
        const words = sentence.split(' ')
        words.forEach(word =>{
          if(word.length <= 2){
            scrambledWord.push(word);
          }else{
            scrambledWord.push(scrambleWord(word));
          }
        })

        setScrambledSentence(scrambledWord.join(' '));
      }, [])


      console.log(scrambledSentence);
    return (
        <div>
            <p id='scrambled-word'>{scrambledSentence}</p>
        </div>
    )
};

export default ScrambleSentence;

https://reactjs.org/docs/hooks-state.html

https://reactjs.org/docs/hooks-effect.html