Javascript 在何处调用setState以正确更新道具

Javascript 在何处调用setState以正确更新道具,javascript,reactjs,Javascript,Reactjs,这是一个全新的反应,我正在制作一个测验应用程序,我需要做以下几点 从一个包含100个问题的外部JS文件(QuizData对象)创建一个包含40个问题的随机数组。这很好,尽管React不是香草JS,但我想知道应该将它们存储在哪里,或者是否应该声明一个如下所示的函数 然后我需要调用setState({questions:questionSet}),将这些新问题分配给我的状态 我需要在我的问题组件中使用它,因为questions[QNum]未定义,所以它当前抛出一个错误 loadQuestions=(

这是一个全新的反应,我正在制作一个测验应用程序,我需要做以下几点

  • 从一个包含100个问题的外部JS文件(QuizData对象)创建一个包含40个问题的随机数组。这很好,尽管React不是香草JS,但我想知道应该将它们存储在哪里,或者是否应该声明一个如下所示的函数
  • 然后我需要调用setState({questions:questionSet}),将这些新问题分配给我的状态
  • 我需要在我的问题组件
    中使用它,因为
    questions[QNum]
    未定义,所以它当前抛出一个错误
  • loadQuestions=()=>{
    设arr=[];
    让问题集=[];
    而(平均长度<40){
    var r=Math.floor(Math.random()*100)+1;
    if(arr.indexOf(r)==-1)arr.push(r);
    }
    arr.sort((a,b)=>a-b.forEach((i)=>questionSet.push(QuizData[i-1]);
    这是我的国家({
    问题:问题集,
    });
    };
    
    …我的问题似乎来自React的协调过程,setState被异步调用。在setState完成之前调用render函数

    我应该在哪里调用setState来加载这些问题?我曾考虑在componentWillmount()中执行此操作,但这已被否决,我尝试在setState中使用回调,但没有成功。只是在寻找处理这类事情的最佳实践


    谢谢

    如果您已经需要(静态)数据,那么最好在构造函数中指定状态

    constructor(props) {
       super(props);
    
       // Set the questionSet
    
       this.state = { questions: questionSet };
    } 
    

    您应该调用
    componentDidMount
    side中的
    loadQuestions
    函数

    class App extends Component {
    
        constructor(props){
             super(props);
             this.state = {questions : [] , ... };
        }
    
        componentDidMount(){
             this.loadQuestions();
        }
    
        ...
    
    }
    
    在渲染方法中,在渲染组件之前 检查它是否未定义

    render() {
    
        ...
        return (
            questions[QNum] ? <Question data={questions[QNum]} /> : <h1>Loading Questions...</h1>
        )
    
    }
    
    render(){
    ...
    返回(
    问题[QNum]?:正在加载问题。。。
    )
    }
    
    我建议您将
    问题存储在状态中。然后将问题映射到
    问题
    组件列表并呈现。像这样:

    class Quiz extends React.Component
    {
        constructor(props) {
            super(props);
            this.state = {
                questions: [],
            }
            this.loadQuestions = this.loadQuestions.bind(this);
        }
    
        loadQuestions() {
            let arr = [];
            let questionSet = [];
            while (arr.length < 40) {
              var r = Math.floor(Math.random() * 100) + 1;
              if (arr.indexOf(r) === -1) arr.push(r);
            }
            arr.sort((a, b) => a - b).forEach((i) => questionSet.push(QuizData[i - 1]));
            this.setState({
              questions: questionSet,
            });
        }
    
        componentDidMount() {
            this.loadQuestions();
        }
    
        render() {
            let questions = [];
    
            this.state.forEach( question => {
                questions.push( <Question key={question.ID} data={question} /> );
            })
    
            return (
                <div>{questions}</div>
            )
        }
    }
    
    类测试扩展了React.Component
    {
    建造师(道具){
    超级(道具);
    此.state={
    问题:[],
    }
    this.loadQuestions=this.loadQuestions.bind(this);
    }
    加载问题(){
    设arr=[];
    让问题集=[];
    而(平均长度<40){
    var r=Math.floor(Math.random()*100)+1;
    if(arr.indexOf(r)==-1)arr.push(r);
    }
    arr.sort((a,b)=>a-b.forEach((i)=>questionSet.push(QuizData[i-1]);
    这是我的国家({
    问题:问题集,
    });
    }
    componentDidMount(){
    这是loadQuestions();
    }
    render(){
    让问题=[];
    this.state.forEach(问题=>{
    问题。推送();
    })
    返回(
    {问题}
    )
    }
    }
    
    使用
    功能设置状态
    可以解决您的问题,这也是推荐的做法。但是你说,你已经试过了,但没有成功。你能分享问题的代码沙盒吗?假设
    是定义了loadQuestions的同一组件的渲染函数的一部分,我认为你需要为
    组件指定一个键,以便在设置状态后重新渲染。这里的
    QNum
    是什么,你如何调用
    ?发布所有相关代码。看起来
    QuizData
    是静态的。如果是这样,我建议将组件外部的所有随机生成内容(与组件无关)提取到一个常规函数中,然后使用下面的答案将其设置为组件构造函数中的状态
    this.state={question:generateRandomQuestions();}
    @palaѕñ
    QNum
    是在我的状态中定义的,我随后对其进行了解构。它将是一个介于1和40之间的整数,当用户循环通过测验时,它将被用来定义他们在哪个问题上。+1到你的第二个片段,-1到你的第一个片段。如果数据已经在道具中,那么您不需要(也不应该将其置于)状态。新开发人员的常见错误。
    class Quiz extends React.Component
    {
        constructor(props) {
            super(props);
            this.state = {
                questions: [],
            }
            this.loadQuestions = this.loadQuestions.bind(this);
        }
    
        loadQuestions() {
            let arr = [];
            let questionSet = [];
            while (arr.length < 40) {
              var r = Math.floor(Math.random() * 100) + 1;
              if (arr.indexOf(r) === -1) arr.push(r);
            }
            arr.sort((a, b) => a - b).forEach((i) => questionSet.push(QuizData[i - 1]));
            this.setState({
              questions: questionSet,
            });
        }
    
        componentDidMount() {
            this.loadQuestions();
        }
    
        render() {
            let questions = [];
    
            this.state.forEach( question => {
                questions.push( <Question key={question.ID} data={question} /> );
            })
    
            return (
                <div>{questions}</div>
            )
        }
    }