我正在尝试在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);
}
}
答案 0 :(得分:1)
我建议您不要在两个地方保存帖子。这有点违背了使用redux的目的。实际上,您不需要在Posts
类中将post作为状态变量使用。每当Redux存储中有新状态时,关联的Class就会进入更新周期。
此外,如果您正在进行api调用,也可以看看redux-thunk
。
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
。
此外,如果您想知道如何显示Loading ...,直到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 })
})
})
}
}
答案 1 :(得分:0)
所以我终于找到了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
}
}
我可以在渲染后看到它
答案 2 :(得分:0)
有时,通过网络获取POST响应可能要花费一些时间。在这种情况下,如果ur组件被挂载,它将调用该动作,但是由于花费时间,您将获得响应为空/未定义的posts数组。 为防止这种情况发生,您可以执行以下操作:
componentDidMount(){
this.props.GetPosts(this.state.posts);
if(!this.props.posts){
console.log(this.props.posts);
}
}
render方法中的tweek可能也有帮助:
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>
);)}
}