繁体   English   中英

获取数据后,React setState不会重新呈现

[英]React setState doesn't re-render after fetching data

如果已经提取了数据,则此代码有效。
但是如果我刷新页面并且不重新渲染元素则不起作用。
如果值得一提,我也在使用Next JS。

class Books extends Component {
    constructor(props) {
        super(props);
        this.state = {
            book: []
        }
        this.renderBooks= this.renderBooks.bind(this);
    }

    renderBooks() {
        let item;
        let items = [];
        return new Promise((resolve, reject) => {
            this.props.ids.forEach(address => {
                firebase.database().ref(`/books/${address}`)
                    .on('value', snap => {
                        item = snap.val();
                    });
                items.push(item);
            })
            resolve(items);
        });
    }

    async componentDidMount() {
        try {
            let res = [];
            res = await this.renderBooks();
            console.log(res);
            this.setState({ book: res });
        } catch (error) {
            console.log(error);
            this.setState(prevState => {
                return { book: 'err' }
              });
        }
    }

    render() {
        return (
            <div>
                { <List grid={{ gutter: 16 }}
                        dataSource={ this.state.book }
                        renderItem={ item => (
                            <List.Item>
                                <Card title={ !!item && item.title }>
                                    ...Book content...
                                </Card>
                            </List.Item>
                        )} />
                }
            </div>
        );
    }
}

export default Books; 

是否有任何关于setState和获取我错过的数据的知识?
PS。 编辑构造函数预订:[]。

您正在使用promise初始化this.state.book 尝试将其设置为null

this.state = {
    book: null
}

您无法使用承诺初始化book 相反,你可以有一个像下面的解决方案。

render方法添加条件渲染,以便知道何时渲染book 在这种情况下,您也不需要返回new Promise

class Books extends Component {
    constructor(props) {
        super(props);
        this.state = { books: null }
    }

    componentDidMount() {
        this.renderBooks()
    }

    renderBooks() {
        this.props.ids.forEach(address => {
            firebase.database().ref(`/books/${address}`)
             .on('value', snap => {
                this.setState({books: [...(this.state.books || []), snap.val()] });
            });
        });
    }

    render() {
        return (
           this.state.books ? 
            <div>
                { <List grid={{ gutter: 16 }}
                        dataSource={ this.state.books }
                        renderItem={ item => (
                            <List.Item>
                                <Card title={ !!item && item.title }>
                                    ...Book content...
                                </Card>
                            </List.Item>
                        )} />
                }
            </div> 
           : 'Initializing'
        );
    }
}

export default Books;

Promise基本上是异步函数,可以在时间解析。

所以,当你这样做

 var item, items = []; // <---- Step 1
 this.props.ids.forEach(address => {
     firebase.database().ref(`/books/${address}`)
         .on('value', snap => {
             item = snap.val(); // <--- Step 3
         });
     });
     items.push(item); // <----- Step 2
 });

步骤是这样的。 所以你在为item分配一个新值items.push(item)之前你正在做items.push(item) snap.val() 这使得item undefined

我猜你的第二个结果是由于缓存。 如果互联网连接是SOOOO FAST, Step 3可能早于Step 2 ,但这是一个不好的假设。 这就是为什么你第二次得到正确的结果。

在这个答案的情况下, snap.val()不是有一个items数组, snap.val()添加到this.state.books中。 但这使它有点重量级。 因为每次调用on('value')查询on('value') ,都会触发setState方法并再次呈现组件。 如果有1000个国家,州将改变1000次。

这就是为什么我不建议您逐个获取所有数据,而是逐个获取数据。 尝试google类似'retrieve multiple data from firebase javascript' 不幸的是,我对firebase了解不多,所以无法帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM