React не передает состояние mapStateToProps - PullRequest
1 голос
/ 13 апреля 2019

Я пытаюсь передать массив элементов (состояние) в mapStateToProps.Однако я получаю пустой массив, или он показывает undefined.

App.js

import React, { Component } from 'react';
import PostList from './PostList';
import Axios from '../Axios';
import {connect} from 'react-redux';
import { withRouter, Redirect} from 'react-router-dom';
import {DeletePost, GetPosts} from '../actions/';

const Styles = {
    myPaper:{
      margin: '20px 0px',
      padding:'20px'
    }
    , 
    wrapper:{
      padding:'0px 60px'
    }
}
class Posts extends Component {
   state = {
      posts: [],
      loading: true,
    }

  getPosts = () => {
    Axios.get(process.env.REACT_APP_GET_POSTS)
    .then( (res) => {
       this.setState({
          posts: res.data,
          loading: false
        })
    })
    // console.log(this.state.posts);
  }
  componentWillMount(){
    this.getPosts();
  }

  componentDidMount(){
    // doesn't show posts in here
    console.log(this.props.posts)
    this.props.GetPosts(this.state.posts);
  }
  onDelete = (id) => {
    Axios.post(`/api/posts/delete/${id}`);
    this.setState({
      posts: this.state.posts.filter(post => post.id !== id)
    })
  }


  render() {
    const {loading, posts} = this.state;
    if (!this.props.isAuthenticated) {
      return (<Redirect to='/signIn' />);
    }
    if(loading){
      return "loading..."
    }
    return (
      <div className="App" style={Styles.wrapper}>
        <h1> Posts </h1>
        <PostList DeletePost={this.onDelete} posts={posts}/>
      </div>
    );
  }
}
const mapStateToProps = (state) => ({
  isAuthenticated: state.user.isAuthenticated,
  posts: state.user.posts
})
const mapDispatchToProps = (dispatch, state) => ({
  // newPost: (post) => dispatch(newPost(post)),
  // DeletePost: (id) => dispatch( DeletePost(id))
  GetPosts: (posts) => dispatch( GetPosts(posts))
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Posts));

Reducer.js

import {  GET_POSTS} from '../actions/';

const initialState = {
    post: [],
    postError: null,
    posts:[]
}

export default (state = initialState, action) => {
    switch (action.type) {
        // doesn't get posts
        case GET_POSTS:
            return({
                ...state,
                posts: action.posts
            })
        default:
            return state
    }

действия

export const GetPosts = (posts) => {
    return (dispatch, getState) => {  
        dispatch({type: GET_POSTS, posts })
        console.log('this works i guess', posts);

    }
}

Ответы [ 3 ]

1 голос
/ 13 апреля 2019

Я бы посоветовал вам не сохранять сообщения в двух местах. Это несколько отрицательно сказывается на использовании редукса. На самом деле вам не нужна запись в качестве переменной состояния в Posts классе. Всякий раз, когда в резервном хранилище появляется новое состояние, Класс попадает в цикл обновления.

Кроме того, вы можете посмотреть на redux-thunk, если вы делаете вызовы API.

import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

Это поможет вам перенести логику извлечения API в действия и редукторы, что сделает ваши представления чистыми.

Изменить это

export const GetPosts = (posts) => {
    return (dispatch, getState) => {  
        dispatch({type: GET_POSTS, posts })
        console.log('this works i guess', posts);

    }
}

до

export const GetPosts = (posts) => {
    return (dispatch, getState) => {
        Axios.get(process.env.REACT_APP_GET_POSTS)
            .then( (res) => {
                 dispatch({type: GET_POSTS, res.data })
             })
        })
    }
}

Изменить это

componentWillMount(){
    this.getPosts();
  }

до

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

Теперь вам не понадобится componentDidUpdate.

Кроме того, если вам интересно, как показать Загрузка ... до тех пор, пока вызов API не будет завершен, вы можете добавить ключ isFetching в свой магазин.

const initialState = {
    post: [],
    postError: null,
    posts:[],
    isFecthing: false
}

и может добавить действие что-то вроде ChangeFetchStats

export const GetPosts = (posts) => {
    return (dispatch, getState) => {
        dispatch({type: CHANGE_STATE, false});
        Axios.get(process.env.REACT_APP_GET_POSTS)
            .then( (res) => {
                 dispatch({type: CHANGE_STATUS, true);
                 dispatch({type: GET_POSTS, res.data })
             })
        })
    }
}
0 голосов
/ 13 апреля 2019

Иногда для получения ответа POST может потребоваться время по сети. В таком случае, если ваш компонент будет смонтирован, он вызовет действие, но, поскольку на это требуется время, вы получите ответ пустой / неопределенный массив записей. Чтобы этого не случилось, вы можете использовать следующее:

    componentDidMount(){
this.props.GetPosts(this.state.posts);

   if(!this.props.posts){
    console.log(this.props.posts);
}

  }

Небольшой твик в методе рендеринга тоже может помочь:

render() {
    const {loading, posts} = this.props;
    if (!this.props.isAuthenticated) {
      return (<Redirect to='/signIn' />);
    }
    if(loading){
      return "loading..."
    }
    return (
{ posts &&(
      <div className="App" style={Styles.wrapper}>
        <h1> Posts </h1>
        <PostList DeletePost={this.onDelete} posts={posts}/>
      </div>
    );)}
  }
0 голосов
/ 13 апреля 2019

Итак, я наконец-то нашел цель для componentDidupdate

Приложению потребовалось немного времени, чтобы загрузить сообщения, может быть, полсекунды.

Итак, позвонив по номеру componentDidUpdate, я получаю сообщения после того, как они закончили рендеринг.

  componentDidUpdate(){
    this.props.GetPosts(this.state.posts);     
  }

Наряду с другим решением @ stevek

изменить это

 case GET_POSTS:
        return({
            ...state,
            posts: state.posts
        })

к этому

import {  GET_POSTS} from '../actions/';

const initialState = {
    post: [],
    postError: null,
    posts:[]
}

export default (state = initialState, action) => {
    switch (action.type) {
        // doesn't get posts
        case GET_POSTS:
            return{...state, posts: action.posts}
        default:
            return state
    }
}

И я могу видеть это после того, как это оказано

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...