即使重新渲染后,React Component也不会渲染新状态

时间:2019-10-21 21:01:37

标签: reactjs components state

基本上,我遇到了一个问题,即React组件将不会渲染来自其状态的数组。该状态确实包含我想要的数组,并且在填充数组var时再次调用render方法,但没有任何显示。

我尝试用伪数据预填充状态数组,它呈现得很好。但是,当我使用函数填充数组时,页面将更新,并且什么也没有显示。如果我检查组件的状态,则它具有所需的数据,但是组件的render方法似乎不想显示它。

import React, { Component } from 'react';
import { withAuthorization } from '../Session';
import { withFirebase } from '../Firebase'; //
import 'firebase/firestore';

const Home = () => (
  <div>
    <h1>Home Page</h1>
    <p>Signed in users only</p>
    <hr />

    <h1>Available Scopes</h1>
    <ScopeRender />

  </div>
);


class ScopeRenderBase extends Component {

    constructor(props) {
        super(props);
        this.state = {
            scopes: []
        }
        //this.componentDidMount = this.componentDidMount.bind(this);
    }

    async componentDidMount() {
        await this.getScopes();
        //console.log(this.state.scopes);
    }

    componentDidUpdate() {
        //console.log(this.state.scopes);
    }

    getScopes() {
        let tempScopes = [];
        this.props.firebase.db.collection("scopes").where("status", "==", 1).get()
            .then( (querySnapshot) => {
                querySnapshot.forEach(function(doc) {
                    tempScopes.push(doc.data().address);
                })
            })
            .catch(function(error) {
                console.log("Error getting documents: ", error);
            });

        //console.log(tempScopes);
        this.setState({ 
            scopes: tempScopes
        });
    }

    render() {
        const displayPosts = this.state.scopes.map((scope, index) =>
            <li key={index}>{scope}</li>
        );
        console.log(this.state.scopes);
        return(
            <div>
                <div>{this.state.scopes}</div>
                <ul>{displayPosts}</ul>
            </div>
        );
    }

}

const ScopeRender = withFirebase(ScopeRenderBase);

const condition = authUser => !!authUser;

export default withAuthorization(condition)(Home);
export { ScopeRender };

使用此代码,状态包含在调用getScopes()函数后所需的数据(作用域),但render方法不会显示数据。

如果我用虚拟字符预填充数据,并像下面那样在componentDidMount()中注释掉getScopes()并保持其他所有内容不变,则虚拟字符显示就很好。

class ScopeRenderBase extends Component {

    constructor(props) {
        super(props);
        this.state = {
            scopes: ['a','b','c']
        }
        //this.componentDidMount = this.componentDidMount.bind(this);
    }

    async componentDidMount() {
        //await this.getScopes();
        //console.log(this.state.scopes);
    }

我希望代码在组件挂载后立即调用getScopes()后,代码将显示来自组件状态的数组的项目符号列表,但没有任何作用。我已经通过开发工具确认了数据确实存在于范围状态数组中,但是render并没有显示它。

2 个答案:

答案 0 :(得分:1)

getScopes内,您将tempScopes填充到then的Promise中,该Promise是异步运行的。 但是在它下面,您也立即调用setState,这意味着在您调用setState时,tempScopes数组仍然为空。 您还应该将通话移至setState内部的then。像这样:

       .then((querySnapshot) => {
            querySnapshot.forEach(function(doc) {
                tempScopes.push(doc.data().address);
            })
            this.setState({scopes:tempScopes});
        })

答案 1 :(得分:0)

和往常一样,发布后不久我就得到了答案。我认为问题出在getScopes函数中。这段代码解决了这个问题。

getScopes() {
    let tempScopes = [];
    this.props.firebase.db.collection("scopes").where("status", "==", 1).get()
        .then( (querySnapshot) => (
            querySnapshot.forEach( (doc) => (
                this.setState((prevState) => ({
                    scopes: [ ...this.state.scopes, doc.data().address ]
                }))
            ))
        ))
        .catch(function(error) {
            console.log("Error getting documents: ", error);
        });
}