admin管理员组文章数量:1426484
So I am trying to scramble a sentence or string and push the words into an array to later join them and output this scrambled sentence but for some reason the useEffect is not running on the first render even with an empty array but when I change one line and run it again it runs as intended. I was just wondering if I was doing anything wrong and how I can change it so that it does run on the first render.
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;
So I am trying to scramble a sentence or string and push the words into an array to later join them and output this scrambled sentence but for some reason the useEffect is not running on the first render even with an empty array but when I change one line and run it again it runs as intended. I was just wondering if I was doing anything wrong and how I can change it so that it does run on the first render.
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;
Share
Improve this question
asked Jan 22, 2022 at 17:52
user17775845user17775845
1
- 1 That useEffect will run (after the first render), try putting in a console log and seeing – nanobar Commented Jan 22, 2022 at 17:54
3 Answers
Reset to default 1Effects don't run during a render.
The first execution of an effect function will be triggered by the first render.
useEffect is called after the first render however the issue in your code is that the words state isn't updated when you think it is.
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.
This code should work:
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/docs/hooks-state.html
https://reactjs/docs/hooks-effect.html
below code will not work as map need return statement, so it would be undefined, useEffect will console the empty array as define in the state. also you should not use let in render ponents as it will always initate, use may be useRef for that. also if your ponent consist js code, better to make it helper file and use it, would save and boost the performance.
words.map(word =>{
if(word.length <= 2){
scrambledWord.push(word);
}
else{
scrambledWord.push(scrambleWord(word));
}
})
本文标签: javascriptWhy is my useEffect not running on first renderStack Overflow
版权声明:本文标题:javascript - Why is my useEffect not running on first render? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745464857a2659487.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论