加载数据后反应更新组件

时间:2018-12-26 16:41:07

标签: node.js reactjs firebase redux google-cloud-firestore

因此,我有一个显示消防站中类别的组件,该组件第一次未显示任何内容,但是当我再次单击导航栏按钮时,它确实显示了存储在消防站中的数据。

这是组件文件:

import * as React from "react";
import Category from "./Category";
import connect from "react-redux/es/connect/connect";
import {getCategories} from "../reducers/actions/categoryAction";

class CategoriesList extends React.Component{
    constructor(props) {
        super(props);
        this.state = ({
            categoriesList: [{}]
        })
    }

    componentWillMount() {
        this.props.getCategories();
        this.setState({categoriesList: this.props.categories});
        this.forceUpdate();
    }

    render() {
        return (
            <div className={'container categories'}>
                <div className={'row center'} onClick={() => this.props.history.push('/addcategories')}>
                    <div className={'col s24 m12'}>
                        <p>Create New Category</p>
                    </div>
                </div>

                <div className={'row'}>
                    <div className={'col s24 m12'}>
                        {/*{() => this.renderCategories()}*/}


                        {this.state.categoriesList && this.state.categoriesList.map(category => {
                            return <Category category={category} key={category.id}/>
                        })}
                    </div>
                </div>
            </div>
        );
    }
}

const mapDisptachToProps = (dispatch) => {
    return {
        getCategories: () => dispatch(getCategories()),
    }
};

const mapStateToProps = (state) => {
    return {
        categories: state.category.categories
    }
};

export default connect(mapStateToProps, mapDisptachToProps)(CategoriesList)

这是化简文件:

 import db from '../firebaseConfig'


const initState = {
    categories: []
};

const categoryReducer = (state=initState, action) => {
    switch (action.type) {
        case 'CREATE_CATEGORY':
            db.collection("Categories").add({
                category: action.category.name
            })
                .then(function(docRef) {
                    db.collection("Categories").get().then((querySnapshot) => {
                        querySnapshot.forEach((doc) => {
                            // console.log(`${doc.id} => ${doc.data().category}`);
                            if(doc.id === docRef.id) {
                                state.categories.push({id: doc.id, name: doc.data().category});
                                console.log(state.categories)
                            }
                        });
                    });
                })
                .catch(function(error) {
                    console.error("Error adding document: ", error);
                });
            break;

        case 'GET_CATEGORIES':
            console.log('Getting data from firestore');

            db.collection("Categories").get().then((querySnapshot) => {
                if(state.categories.length !== querySnapshot.size) {
                    querySnapshot.forEach((doc) => {
                        state.categories.push({id: doc.id, name: doc.data().category});
                    });
                }
            });
            break;
    }
  return state;
};

export default categoryReducer

完全加载数据后,是否有任何方法可以更新组件?还是将所有数据加载到initalState中的方法?

2 个答案:

答案 0 :(得分:2)

人们需要了解的东西很少。首先,this.props.getCategories()执行的操作本质上是异步的,因此在下一行this.setState({categoriesList: this.props.categories});中,我们将无法获取所需的数据。

第二,不必要存储道具而无需进行任何修改,并且会导致复杂化。因此,尝试不使用道具而直接使用道具。如果您要修改获得的道具,请确保适当地覆盖getDerivedStateFromProps

第三,尝试使用componentDidMountcomponentWillMount执行这样的异步操作。请参阅when to use componentWillMount instead of componentDidMount

第四(在您的情况下重要),Reducer不应包含异步操作。减速器应为同步操作,它将返回新状态。对于您而言,您需要先从其他地方获取数据,然后在dispatch 回调中获取db.collection(..).then。如果您使用过多的异步操作来更新您的Redux,则也可以使用redux-thunk

因此,如果您遵循在简化器中返回新状态而不是直接在db().then callback

中对redux进行突变的第四点,则@ Mis94答案应该有效。

答案 1 :(得分:0)

首先,您不需要将组件的道具存储在状态对象中。实际上,这被视为反应中的anti-pattern。无需执行此操作,只需在渲染方法中直接使用道具即可:

render() {
    return (
        <div className={'container categories'}>
            <div className={'row center'} onClick={() => this.props.history.push('/addcategories')}>
                <div className={'col s24 m12'}>
                    <p>Create New Category</p>
                </div>
            </div>

            <div className={'row'}>
                <div className={'col s24 m12'}>
                    {/*{() => this.renderCategories()}*/}


                    {this.props.categories && this.props.categories.map(category => {
                        return <Category category={category} key={category.id}/>
                    })}
                </div>
            </div>
        </div>
    );
}

因此,在您的componentWillMount中,您只需发起请求:

componentWillMount() {
    this.props.getCategories();
}

您也可以使用componentDidMount()生命周期方法进行操作。

现在,当您的请求得到解决并且类别在商店(Redux)中更新时,它们将再次传递给您的组件,从而导致其更新。商店中存储的类别中的每次更新也会发生这种情况。

除非您有实现forceUpdate生命周期方法的组件并且希望它们忽略它并进行强制更新,否则不必调用shouldComponentUpdate。您可以阅读所有这些生命周期方法(如果使用React,则必须阅读)here