My redux store updates but react view doesn't

I saw similar problems on Stackoverflow but the problem was that they mutate the state and that doesn’t let react-redux update the view I don’t know if I have the same problem but I used this code structure in previous project and it worked fine please help .

the reducer code
I use the same structure in similar apps and it works . in the redux devtools the store gets updated already but that didn’t change the React view.

import * as actionTypes from '../actions/constants';

export default (state = [], action) => {
  switch (action.type) {
    case actionTypes.LOAD_ALL_POSTS:
      return [...state, ...action.allPosts];
    case actionTypes.ADD_POST:
      return [...state, action.post];
    case actionTypes.EDIT_POST:
      return state.map(post => {
        if (post.id === action.id) {
          return {
            ...post,
            ...action.updates,
          };
        }
        return post;
      });
    case actionTypes.DELETE_POST:
      return state.filter(({ id }) => id !== action.id);
    default:
      return state;
  }
};

Here are my actions and I use react-redux to connect redux with react the redux is connected with react successfully and the LOAD_ALL_POSTS action is working correctly but when I try to use ADD_POST action it only updates the store
and didn’t update the view.

import uid from 'uuid';
import * as actionTypes from './constants';

export const loadAllPosts = (allPosts = []) => ({
  type: actionTypes.LOAD_ALL_POSTS,
  allPosts,
});

export const loadLatestPosts = num => ({
  type: actionTypes.LOAD_FEATURED_POSTS,
  number: num,
});

export const addPost = post => ({
  type: actionTypes.ADD_POST,
  post: { ...post, id: uid() },
});

export const editPost = (id, updates = {}) => ({
  type: actionTypes.EDIT_POST,
  id,
  updates,
});

export const deletePost = id => ({ type: actionTypes.DELETE_POST, id });

//connect Redux with React 

const mapStateToProps = state => ({
  posts: state.posts,
});

export default connect(mapStateToProps, { filterByType })(Projects);

The reducer state is an array of objects I use array.map to loop through its items and render them in React Component.

Store
this is configurStore();

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import posts from '../reducers/posts';
import filters from '../reducers/filters';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default () => {
  const store = createStore(
    combineReducers({
      posts,
      filters,
    }),
    composeEnhancers(applyMiddleware(thunk))
  );

  return store;
};

What does the react component look like?

Could you upload this to github so we can download and troubleshoot the code?

here is the git repo Git Repo
it is my new website you can visit the route that the problem is happening in by typing /admin
as you can see it is a controlled form and the redux action parameter is the conatiner state.post

it isn’t finished yet obviously :joy::joy: and thanks for your attention and time

OK, that’s an awful lot of code and files and components to go through. You’re going to have to tell us exactly how to duplicate the problem (and since your UI isn’t done you’ll have to tell us how to get there) and you need to tell us what you thought was going to happen and what is actually happening.

Just looking at this code a little,

Yeah, mutating state can be a problem. As are problems with the key in lists and not referencing the props/state properly.

I would try to pin exactly where the problem is. This is where I start putting in console.log messages and see exactly where in the code, where it is that what I think should be happening isn’t. It doesn’t sound like you’ve found that yet? Is the component recieving the new props and not responding? Is the parent component getting them if it’s being passed by props or is it mapStateToProps - is that getting the changes? Find out where the break is - it will be much easier to diagnose once you’ve done that.

I do see that the selectPosts function is intercepting and filtering the props - see if there is a problem in that chain? Find out where the break is.

1 Like

well the route where the action is admin route you can see the index file in the admin folder and its
children what I expect to happen when this action is triggered is to add another object to the state of posts reducer I expect the /projects page to have a new project but this didn’t happen it receives data from redux through mapStateToProps func and the data props didn’t get updated after the action in admin get dispatched . But there is something strange in the home page I put a button that when clicked dispatch the ADD_POST action and it worked fine may be the problem is on the Admin component or its children .

Again, I’m asking for very specific instructions on how to duplicate the problem.

And, again, what trouble shooing have you done? You should be able to narrow down exactly where the disconnect is.

in the admin/index.js file addPost() action doesn’t change the view in the redux dev-tools the store state changes but the view doesn’t.
in other components the same action works fine .

Yes, but how do I get that addPost to fire programatically? What route and what button do I push? I spent 20 minutes with your code last night and could not figure it out.

1 Like

sorry for that , and I really appreciate your effort and time thank you , to get to the form you should go to /admin and the button that fires the action is the submit button in the top of the form and you can find the form code in AdminForm component the action is get passed as a prop to the AdminFrom through its parent (index.js in the Admin folder inside components folder ). you can find where the action in the Parent it is in the onSubmit method .

Update
the redux store updates only on the /admin route and doesn’t update on other routes
this is the mapStateToProps I used in both components

const mapStateToProps = state => {
  console.log(state.posts);
  return {
    posts: state.posts,
  };
};
export default connect(mapStateToProps, { addPost })(Admin);

state.posts updates when the action fires in Admin component but on the other component it is the same when the action fires

So the real problem is that the redux store dosn’t update in all the routes

OK, that is a contradictory statement. By definition, a Redux store is the “single source of truth”. It would be like saying that a book is a different book depending on whether you or I are reading it. More likely is that either we are talking about two different books, or one or both of us is reading it wrong.

I think it is the former in this case.

First of all, when I go to /admin and add a post, I see that it is indeed created. When I go to the /projects/all route, I see that it is gone. Looking in devtools/network I see that when I typed in that url, the browser saw it as a new web page and reloaded everything. (I assume that that’s how you’re getting from page to page as there are no buttons.) So the point isn’t that the store is one thing in one place and another in a different place, the point is that as you switch routes, you are causing the entire page to reload from scratch and your dummy data gets reloaded, obliterating any changes you made.

I think React Router wants to handle your routing. So I added a button into the admin route to switch to the projects route programatically:

import { Route } from 'react-router-dom' // top of the file, with the imports

// the rest of the code ...

  render() {
    const { title, desc, tags, headerImage, type, content } = this.state.post;
    const Button = () => (
      <Route render={({ history}) => (
        <button
          type='button'
          onClick={() => { history.push('/projects/all') }}
        >
          go proj
        </button>
      )} />
    )
    return (
      <div className="admin-page">
        <Button />
        <PreviewPost
//...

This works. I can add a post, hit that button, and go to other route, and the new post is there with all the old ones.

So, I conclude two things:

  1. You need to navigate programatically.
  2. You need a mechanism to handle if people type in the url. This will probably take care of itself when you persist your data, i.e. save the new post in the DB, etc. That way when the page reloads it will go get the data from the DB, or whatever and it will still be there.
2 Likes

Thank you very much for your help and time . yes it now works as expected I thought that when I leave the projects/all tab opened in another tab it didn’t reload every time I switch back to it . that was the cause of the problem . thank you again :smiley:

I think the browser just sees that you’ve manually changed the url and assumes that it is a new web site so it loads it from scratch. Once you get your save/load data from the DB set up, it should be OK.

1 Like

Although seems a trivial thing, this same issue had me banging my head. No amount of googling solved my issue and thanks Kevin for this superb reply. This solved my problem. My redux state was not being fetched in some of the components and I realized it from your post, and I was using an href and changed it to react Link. Voila, that resolved my issue which was giving me a headache for nearly a week.

Thanks again for your superb answer

1 Like