React Redux不同步mapStateToProps中的道具

时间:2019-02-12 12:51:02

标签: javascript reactjs asynchronous firebase-realtime-database redux

我正在将React redux与Firebase实时数据库一起使用。 在App.js中,我正在调度动作fetchAllPosts

App.js

class App extends Component {
  componentDidMount() {
    this.props.fetchAllPosts();
  }
  render() {
    return (
      <div className="App">
          // something ...
      </div>
    );
  }
}
const mapDispatchToProps = dispatch => {
  return {
      fetchAllPosts: () => {dispatch(allPosts())}
  }
}

我的动作如下所示(我在使用redux-thunk):

动作

export function allPosts() {
    return (dispatch) => {  
firebase.database().ref('posts/').on('value', (snapshot) => {
        dispatch({type: "ALL_POSTS", postsArray: snapshot.val(), loading: false})
    })
    }
}

然后我正在组合减速器(我知道在这种情况下没有必要):

const rootReducer = combineReducers({
    allPosts: postsReducer
})

我的减速器看起来像这样:

减速器

const initialState = {
    allPosts: []
}

const postsReducer = (state = initialState, action) => {
    switch(action.type) {
        case "ALL_POSTS" :
        console.log("action payload all posts", action.postsArray)
        return {
            ...state,
            loading: false,
            allPosts: action.postsArray
        }
        break;
        default:
        return state
    }
    return state
}

最后:我的SinglePostview组件如下所示: SinglePostview.js

import React, {Component} from 'react';
import {connect} from 'react-redux';

class SinglePostview extends Component {
    render() {
        console.log("ppp", this.props)
        return (
            <h2>{this.props.post.title}</h2>
        )
    }
}

const mapStateToProps = (state, ownprops) => {
    const postId = ownprops.match.params.postid
    return {
        post: state.allPosts.allPosts[postId]
    }
}

export default connect(mapStateToProps)(SinglePostview);

在执行render方法时,this.props.post未定义,并且出现错误:

  

TypeError:无法读取未定义的属性“ title”。

问题是:当应用程序首次加载时,props.post是未定义的(所以我有一个错误),大约1秒钟后,它收到了值,但没有任何改变-错误仍然存​​在存在并且该值不显示。 有人可以帮我吗?

2 个答案:

答案 0 :(得分:2)

假设您的减速器没问题,您可以通过以下方式解决此问题

更改此

render() {
        return (
            <h2>{this.props.post.title}</h2>
        )
    }

对此:

render() {
        if (!this.props.post){
            return null;
        }
        return (
            <h2>{this.props.post.title}</h2>
        )
    }

render() {
        return (
            <h2>{this.props.post && this.props.post.title}</h2>
        )
    }

答案 1 :(得分:0)

您正在将allPosts定义为数组

    const initialState = {
    allPosts: []
    }

但是您试图像访问对象一样访问它。

state.allPosts.allPosts[postId]

因此,如果您的state.allPosts.allPosts是一个数组,请尝试使用ES6 find()方法从具有postId的数组中获取帖子。

假设

state.allPosts.allPosts = [
   {postId: 1,title:'abcd'},
   {postId:2,title:'def'}
]
 state.allPosts.allPosts.find(post => postId === post.postId)