如何在反应中只运行一次功能
Posted
技术标签:
【中文标题】如何在反应中只运行一次功能【英文标题】:How to run a function only once in react 【发布时间】:2021-02-20 18:12:37 【问题描述】:我正在开发一个简单的测验应用程序。我有一个本地数组,其中包含每次随机顺序的问题。每次运行 handleAnswerOptionClick 时都会触发以不同顺序打乱数组的函数。
怎样才能运行一次arrayShuffle函数?
我的猜测是我可以为此使用 useEffect,但我还没有让它工作。它抱怨它没有不同的依赖关系。
useEffect(() =>
arrayShuffle(questions);
, []);
代码:CodeSandox
测验容器:
import React, useState, useEffect from "react";
export const QuizContainer = () =>
const questions = [
questionText: "What is the capital of France?",
answerOptions: [
option: "New York", isCorrect: false ,
option: "London", isCorrect: false ,
option: "Paris", isCorrect: true ,
option: "Dublin", isCorrect: false
]
,
questionText: "Who is CEO of Tesla?",
answerOptions: [
option: "Jeff Bezos", isCorrect: false ,
option: "Elon Musk", isCorrect: true ,
option: "Bill Gates", isCorrect: false ,
option: "Tony Stark", isCorrect: false
]
,
questionText: "The iPhone was created by which company?",
answerOptions: [
option: "Apple", isCorrect: true ,
option: "Intel", isCorrect: false ,
option: "Amazon", isCorrect: false ,
option: "Microsoft", isCorrect: false
]
,
questionText: "How many Harry Potter books are there?",
answerOptions: [
option: "1", isCorrect: false ,
option: "4", isCorrect: false ,
option: "6", isCorrect: false ,
option: "7", isCorrect: true
]
];
const [currentQuestion, setCurrentQuestion] = useState(0);
const [showScore, setShowScore] = useState(false);
const [score, setScore] = useState(0);
// Event handlers
const handleAnswerOptionClick = (isCorrect) =>
if (isCorrect)
setScore(score + 1);
const nextQuestion = currentQuestion + 1;
nextQuestion < questions.length
? setCurrentQuestion(nextQuestion)
: setShowScore(true);
;
// ShuffleArray
const arrayShuffle = function (arr)
let newPos, temp;
for (let i = arr.length - 1; i > 0; i--)
newPos = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[newPos];
arr[newPos] = temp;
return arr;
;
const newArray = arrayShuffle(questions);
console.log(newArray);
return (
<>
<h1>QuizContainer</h1>
showScore ? (
<p>
You scored score out of questions.length
</p>
) : (
<>
<p>
Question currentQuestion + 1/questions.length
</p>
<p>questions[currentQuestion].questionText</p>
<div>
questions[currentQuestion].answerOptions.map(
(answerOption, index) => (
<div key=index>
<button
onClick=() =>
handleAnswerOptionClick(answerOption.isCorrect)
>
answerOption.option
</button>
</div>
)
)
</div>
</>
)
</>
);
;
请问我是否需要澄清,以及你们是否认为我的处理方式正确。
先谢谢了,
埃里克
【问题讨论】:
【参考方案1】:两件事:
-
如果您希望函数在挂载时运行,请使用带有空依赖项数组的
useEffect
,并且您可以放心地忽略这种情况下的 linter 警告并且仅在这种情况下。
这不是(据我所知)您想要的:您希望在页面加载时运行一次,然后再也不运行。
如果是这样,那么甚至没有必要将其放入组件中。将其拉出到它自己的***事物中:
const questions = [
questionText: "What is the capital of France?",
answerOptions: [
option: "New York", isCorrect: false ,
option: "London", isCorrect: false ,
option: "Paris", isCorrect: true ,
option: "Dublin", isCorrect: false
]
,
questionText: "Who is CEO of Tesla?",
answerOptions: [
option: "Jeff Bezos", isCorrect: false ,
option: "Elon Musk", isCorrect: true ,
option: "Bill Gates", isCorrect: false ,
option: "Tony Stark", isCorrect: false
]
,
questionText: "The iPhone was created by which company?",
answerOptions: [
option: "Apple", isCorrect: true ,
option: "Intel", isCorrect: false ,
option: "Amazon", isCorrect: false ,
option: "Microsoft", isCorrect: false
]
,
questionText: "How many Harry Potter books are there?",
answerOptions: [
option: "1", isCorrect: false ,
option: "4", isCorrect: false ,
option: "6", isCorrect: false ,
option: "7", isCorrect: true
]
];
const arrayShuffle = function (arr)
let newPos, temp;
for (let i = arr.length - 1; i > 0; i--)
newPos = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[newPos];
arr[newPos] = temp;
return arr;
;
const newArray = arrayShuffle(questions);
export const QuizContainer = () =>
/* rest of component */
如果您确实想重新运行它但又想控制这样做,您可以将其置于状态:
export const QuizContainer = () =>
const [shuffled, setShuffled] = useState(arrayShuffle(questions));
const reShuffle = () => setShuffled(arrayShuffle(questions));
/* rest of the component */
但一般来说,不要使用静态常量来混淆组件定义,这些常量在整个页面浏览中都保持不变。
【讨论】:
关于(1):只要questions
不改变,添加到dependencies数组就没有错。
@JonasWilms 绝对是,但我相信你知道我们每天会收到 50 个关于 linter 抱怨空依赖数组的问题。
啊,我明白了!这很简单,因为它在组件内部。我将进一步研究 useEffect 依赖项,但感谢您为我指明正确的方向。 // 埃里克@JaredSmith
@erikos93 我很高兴,是的:请记住,任何不属于钩子的代码(以及钩子中的很多内容)都会在每次安装组件时重新运行,并且每次应用程序状态发生变化时,组件都可能会重新挂载(有一些方法可以改变它,但我们正误入歧途)。【参考方案2】:
你只能像这样一次运行一个函数
import React, useEffect, useState from "react";
const Component = () =>
const [functionCount,setFunctionCount] = useState(0);
useEffect(() =>
if (functionCount == 0) MyFunction()
)
const MyFunction = () =>
// Code here
setFunctionCount(functionCount + 1);
return (<h1> functionCount </h1>);
export default Component;
【讨论】:
如果状态会改变,组件将被重新渲染并且useEffect重新运行以上是关于如何在反应中只运行一次功能的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React hooks 和 redux 中只获取一次且不再获取数据