未调用的动作创建者

时间:2016-10-11 15:07:52

标签: reactjs redux

我不是百分之百确定它是否正常工作,但是它确实给出了我所遵循的视频课程的结果。

renderPosts只是假设要呈现列表,而是第一次得到一个空白数组。当第二次调用mapStateToProps时,数组将填充预期的值。

就好像第一次调用mapStateToProps一样,它没有先通过动作创建者或其他东西。

COMPONENT

import React, {Component} from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '../actions/index';
import { Link } from 'react-router';

class PostsIndex extends Component {
    componentWillMount() {
        console.log("componentWillMount");
        this.props.fetchPosts();
}

renderPosts() {
    // console.log("renderPosts - this.props.posts",this.props.posts);
    if(this.props.posts){
        return this.props.posts.map((post) => {
            return (
                <li className="list-group-itme" key="{post.id}">
                    <span className="pull-xs-right">{post.catagories}</span>
                    <strong>{post.title}</strong>
                </li>
            );
        });
    }
}

render() {
    return (
        <div>
            <div className="text-xs-right">
                <Link to="/posts/new" className="btn btn-primary">
                    Add New Post
                </Link>
            </div>
            <h3>Posts</h3>
            <ul className="list-group">
                {this.renderPosts()}
            </ul>
        </div>
    );
}
}

function mapStateToProps(state) {
    console.log("mapStateToProps",state.posts);
    return {posts: state.posts.all}
}

export default connect(mapStateToProps, {fetchPosts})(PostsIndex);

ACTION

import axios from 'axios';

export const FETCH_POSTS = 'FETCH_POSTS';
export const CREATE_POST = 'CREATE_POST';

const ROOT_URL = 'http://reduxblog.herokuapp.com/api';
const API_KEY = '?key=qwerty123';

export function fetchPosts(){
    const request = axios.get(`${ROOT_URL}/posts${API_KEY}`);

    return {
        type: FETCH_POSTS,
        payload: request
    };
}

export function createPost(props) {
    const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, props);

    return{
        type: CREATE_POST,
        payload: request
    }
}

REDUCER

import { FETCH_POSTS }  from '../actions/index';

const INITIAL_STATE = { postsList:[], post:null };

export default function(state = INITIAL_STATE, action){
    console.log("action.type",action.type);

    switch (action.type) {
        case FETCH_POSTS:
            return {...state, postsList: action.payload.data};

        default:
            return state;
    }
}

mapStateToProps被调用两次。在初始调用时,数组为空。在第二个电话中,我在阵列中有十个帖子。

问题是它似乎想渲染第一个数组并忽略第二个

我在

中放了一个consol.log

renderPosts 和

mapStateToProps 它呈现如下。

控制台
enter image description here

任何想法?

2 个答案:

答案 0 :(得分:0)

我认为错误来自您处理Promise的方式。第一次在控制台中看到mapStateToProps时,您可以看到没有数据,所以这是PENDING,第二次是它完成了.FILFILLED。你需要找到一种方法来解决这个问题。

示例但不是最好的,我想如果声明,你可以改变你。

function loadFile(filePath){
    var arrLines = [];
    fs.stat(filePath, function(err, stat) {
        if(err == null) {
            arrLines = fsReadFileSynchToArray(filePath);
        } else if(err.code == 'ENOENT') {
            console.log('error: loading file ' + filePath + ' not found');
        } else {
            console.log('error: loading file', err.code);
        }
    });
    return arrLines;
}

第二个应该是改变你做出承诺的方式。一个好的图书馆是redux-promise-middleware

这是我的应用程序的一个例子。

操作

    import React, {Component} from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '../actions/index';
import { Link } from 'react-router';

class PostsIndex extends Component {
    componentWillMount() {
        console.log("componentWillMount");
        this.props.fetchPosts();
}

renderPosts() {
    return this.props.posts.map((post) => {
        return (
            <li className="list-group-itme" key="{post.id}">
                <span className="pull-xs-right">{post.catagories}</span>
                <strong>{post.title}</strong>
            </li>
        );
    });
}

render() {
    return (
        <div>
            <div className="text-xs-right">
                <Link to="/posts/new" className="btn btn-primary">
                    Add New Post
                </Link>
            </div>
            <h3>Posts</h3>
            <ul className="list-group">
                {this.props.posts !== [] this.renderPosts() : <h1>Loading...</h1>}
            </ul>
        </div>
    );
}
}

function mapStateToProps(state) {
    console.log("mapStateToProps",state.posts);
    return {posts: state.posts.all}
}

export default connect(mapStateToProps, {fetchPosts})(PostsIndex);

减速

export const reqAllGames = games => {

  const promise = new Promise((resolve, reject) => {
    request
      .get(`${config.ROOT_URL}/${config.API_KEY}`)
      .end((err, res) => {
        if (err) {
          reject(err);
        } else {
          resolve(res.body.top);
        }
      });
  });

  return {
    type:    types.RECEIVE_ALL_GAMES,
    payload: promise
  };

};

组件

import * as types from "../constants/";

const gameReducer = (games = { isFetched: false }, action) => {

  switch (action.type) {
    case `${types.RECEIVE_ALL_GAMES}_PENDING`:
      return {};
    case `${types.RECEIVE_ALL_GAMES}_FULFILLED`:
      return {
        games:     action.payload,
        err:       null,
        isFetched: true
      };
    case `${types.RECEIVE_ALL_GAMES}_REJECTED`:
      return {
        games:     null,
        err:       action.payload,
        isFetched: true
      };
    default:
      return games;
  }

};

export default gameReducer;

如果您使用react-router,您可以使用onEnter api并在此处执行操作。有了这个你就知道你的组件会得到帖子。 RallyCoding https://www.youtube.com/watch?v=JicUNpwLzLY

是一个很好的教程

希望能帮到你

答案 1 :(得分:0)

https://www.udemy.com/react-redux/learn/v4/questions/1693796

在您的reducer中,您将帖子列表分配给键postsList

case FETCH_POSTS:
            return {...state, postsList: action.payload.data};

我们可以通过查看屏幕截图中的postsList控制台日志来确认它们是否正确地被假定为mapStateToProps

但是,mapStateToProps正在查看属性state.posts.all

return {posts: state.posts.all}

帖子列表未分配给all属性,它们被分配到postsList属性。这就是您没有在组件中看到更新的帖子列表的原因。您需要更新reducer放置帖子列表的属性,或更新您的mapStateToProps以从正确的属性中提取帖子列表。

-Stephen Grider