randal
randal

Reputation: 1362

How to pass state as a redux action

I'm trying to find a way to pass a state to an action or a reducer. For example

I want to be able to run the onDelete function on the action then update the state on the reducer. However, in order for this to work, i would need to filter through the posts then i would able to remove a post.

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();
  }

 // run this logic on the reducer or on actions.
  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>
    );
  }
}

Here is the attempt to make into an action, which technically works.

actions

export const DeletePost =  (id) => { 
    return (dispatch) => {
       return Axios.post(`/api/posts/delete/${id}`)
            .then( () => {
                dispatch({type: DELETE_POST, id});
            });
    }
}

Then we approach the problem of actually getting the posts on the reducer. The problem is that the reducer does not know where the posts are coming from, its undefined. So i want to know how would i pass the state to the reducer.

and will return

state.posts.filter is not a function or something along those lines.

reducer.js

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

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

export default (state = initialState, action) => {
    switch (action.type) {

        case DELETE_POST:
            return ({
                ...state,
               posts: state.posts.filter(post=> post.id !== action.id)
            })
        default:
            return state
    }
}

How would i get pass the state to the actions, so that i would be able to update the state on the reducer ?

Upvotes: 1

Views: 1202

Answers (1)

Matthew Liu
Matthew Liu

Reputation: 319

I'm trying to find a way to pass a state to an action or a reduce

The way you wrote your actions code indicates you're using redux thunk, which means you can access the getState function in your action. Example usage of getState is here

export const DeletePost =  (id) => { 
    return (dispatch, getState) => {
       return Axios.post(`/api/posts/delete/${id}`)
            .then( () => {
                dispatch({type: DELETE_POST, id});
            });
    }
}

you already have access to the state in your reducer code. Its called state!


Now, the above could the end of the answer. But I'm questioning the premise of what you're doing in the class.

 // run this logic on the reducer or on actions.
  onDelete = (id) => {
    Axios.post(`/api/posts/delete/${id}`);
    this.setState({
      posts: this.state.posts.filter(post => post.id !== id)
    })
  }

Above you're filtering for the posts after you've already filtered/deleted it from redux (i.e. you're filtering unnecessarily twice). You should instead just be getting the state directly from redux

Take a look here. For an example of this being used in a more robust setting. I would direct you to this example. For the example, look at src/containers/visibleTodoList

So really for what you're doing, posts should just live with redux and not in the class component!


Lastly for the error you saw

state.posts.filter is not a function or something along those lines.

Could you give the exact error? your reducer code seems fine.

Upvotes: 2

Related Questions