简体   繁体   中英

react js with redux, my container isn't receiving data after success actions / reducers

I am a bit confuse. So I started react 2 weeks ago and redux recently (still in learning), I decided to have a go.

So I am just trying to make an API fetch and display the list.

Then I am quite proud, from my container :

import React, { Component, PropTypes } from 'react';

import { fetchPosts, invalidateReq } from '../actions/ajaxactions';
import DisplayWikiList from '../components/trending';
import DisplayBroadmatchList from '../components/trending';
import ColumnName from '../components/trending';
import DisplayOutPut from '../components/trending';

var Redux = require('redux');
var ReactRedux = require('react-redux');
var Card = require('material-ui/lib/card/card');

const { connect } = ReactRedux;


export default class DisplayTrendings extends Component {
  constructor(props) {
    super(props)
  }

  componentDidMount() {
    const { dispatch } = this.props;
    dispatch(fetchPosts('trendings'));
    document.title = 'Blippar-wise Trendings - Blippar Dashboard';
  }

  render() {
    const { posts, isFetching } = this.props;
    console.log("posts :", posts);
    const isEmpty = posts.length === 0;
    return (
      <Card className="card-main">
          <h2 className="trending-title">Trendings</h2>
          <ColumnName />

          {isEmpty
            ? (isFetching ? <h2>Loading...</h2> : <h2>Empty request.</h2>)
            : <div className="col-md-6">
                <DisplayWikiList style={{ opacity: isFetching ? 0.5 : 1 }} posts={posts} />
              </div>
          }

          <div className="col-md-6">
            <div className="row">
              <div className="col-xs-6">
                <input type="text" className="bespoke-label" />
              </div>
              <DisplayOutPut />
            </div>
          </div>
      </Card>
    );
  }
};

DisplayTrendings.propTypes = {
  posts: PropTypes.array,
  isFetching: PropTypes.bool,
  dispatch: PropTypes.func
};

function mapStateToProps(state) {
  const {
    isFetching,
    items: posts
  } = {
    isFetching: true,
    items: []
  }
  return {
    posts,
    isFetching
  };
};

export default connect(mapStateToProps)(DisplayTrendings)

I have the flow going perfectly through my actions :

import fetch from 'isomorphic-fetch'

var Config = require('../configuration/config');

export const REQUEST_POSTS = 'REQUEST_POSTS'
export const RECEIVE_POSTS = 'RECEIVE_POSTS'
export const INVALIDATE_REQ = 'INVALIDATE_REQ'

export function invalidateReq(value) {
  return {
    type: INVALIDATE_REQ,
    value
  };
};

function requestPosts(value) {
  return {
    type: REQUEST_POSTS,
    value
  };
};

function receivePosts(json) {
    return {
        type: RECEIVE_POSTS,
        posts: json
    };
};

export function fetchPosts(value) {
    return dispatch => {
        dispatch(requestPosts(value));
        return fetch(Config.serverUrl + '/' + value, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                Authorization: Config.authorizationToken
            },
        })
          .then(response => response.json())
          .then(json => dispatch(receivePosts(json)))
    };
};

and then it's correctly dispatch to my reducers !

import { combineReducers } from 'redux'
import {
  INVALIDATE_REQ,
  REQUEST_POSTS, RECEIVE_POSTS
} from '../actions/ajaxactions'

function posts(state = {
  isFetching: false,
  didInvalidate: false,
  items: []
}, action) {
  switch (action.type) {
    case INVALIDATE_REQ:
        return Object.assign({}, state, {
            didInvalidate: true
        });
    case REQUEST_POSTS:
        return Object.assign({}, state, {
            isFetching: true,
            didInvalidate: false
        });
    case RECEIVE_POSTS:
        return Object.assign({}, state, {
            isFetching: false,
            didInvalidate: false,
            items: action.posts
        });
    default:
      return state;
  }
};

const rootReducer = combineReducers({
    posts
});

export default rootReducer;

YES! Super! (Let me add that I checked all of it with some very smart console.logs)

But then, my page is freeze on "isFetching" (loading) and when I check the value "posts" on my container, it's definitely empty :(

Can someone help me doing the connexion between the redux flow and then my container ? Or am I doing something terribly wrong in this code ?

Many thanks guys!

Edit: this is what I have in the console when I load my page:

在此处输入图片说明

In your container, you are setting isFetching to true, so it will always be true.

It appears you are perhaps trying to set default state, but this wouldn't be the place for that.

function mapStateToProps(state) {
  const {
    isFetching,
    items: posts
  } = {
    isFetching: true, // <-- this will always be true
    items: []
  }
  return {
    posts,
    isFetching
  };
};

After having a week break from this refacto project, I was able to figure out the problem.

When elements are changing, reactJs gravite around the state property, which I wasn't using this whole time...

So, thx to Chris who wrote a first answer, I was able to figure out the problem.

Instead of writing:

function mapStateToProps(state) {
  const {
    isFetching,
    items: posts
  } = {
    isFetching: true,
    items: []
  }
  return {
    posts,
    isFetching
  };
};

Which was quite weird now I think of it, I switch for the state solution, which was just in front of me this whole time:

function mapStateToProps(state) {
  console.log("state: ", state);
  const {
    isFetching,
    items: posts
  } = {
    isFetching: state.posts.isFetching,
    items: state.posts.items
  }
  return {
    posts,
    isFetching
  };
};

And it works! Wuhuuu!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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