I cant get Redux state Change to Rerender component if the state value is the same

Viewed 80

So I'm having a problem that I can't wrap my head around, I am using: react redux store And nodejs backend

I have a modal component that opens and allows the user to change the user avatar, And I have a parent component that should show the current user avatar

After the modal opens and the user picks the file they want, The file is sent to the server via an Axios post request and the server always rewrites the previous avatar so the link is always the same if I want to access the avatar I go to this URL : http://localhost:3001/users/${action._id}/avatar

I first thought that I could use the URL in my image src for the parent element but when the avatar changed the parent component did not rerender so the static URL was not a good option

So I decided to store a new variable in my redux store called an avatar and store the static URL in the store giving the store.user.avatar as the src for my image and every time I make an Axios post request I also set the store value to the same static STRING URL, but as the value of the string did not change and was the same it was not causing a rerender

So I thought as javascript objects are never considered equal as in {url:1} != {url:1} Maybe if store the URL in an object it would evaluate to not the same and cause a rerender but it did not work !!

this is my redux store I'm using mapStateToProps and setting the value of the image to be the value of the URL in the state:

        const mapStateToProps = (state) => {
      return {
        userAvatar: state.user.avatar.url,
      };
    };
    
    export default connect(mapStateToProps)(Header);

These are the Actions that I dispatch on upload click :

    export const setUserAvatar = (avatar) => ({
      type: "SET_USER_AVATAR",
      avatar,
    });
    
    export const startSetUserAvatar = (file, userAvatarURLForStateChange) => (
      dispatch
    ) => {
      let formData = new FormData();
      formData.append("avatar", file);
      return axios({
        url: "/users/me/avatar",
        method: "POST",
        data: formData,
      })
        .then((res) => {
          dispatch(setUserAvatar(userAvatarURLForStateChange));
          return res.status;
        })
        .catch((err) => {
          console.log("avatar upload action error :", err);
          return err;
        });
    };

and this is my Reducer :

    case "SET_USER_AVATAR":
      return {
        ...state,
        avatar: { ...action.avatar },
      };

So here I am 10 hours later needing your generous help

1 Answers

ok so after countless struggles I realized what I was doing wrong reactjs is not checking the state changes for the reRender at the end of the day it just cares about the virtualDOM so if the state changes but the values don't change that means the virtualDom is exactly the same and it will not reRender,

so in my case even setting the state avatar to an object containing the URL did not change the img src attribute resulting in NOT RENDERING

to work around this someone on the discord channel propose adding a query string at the end of the URL for example I added a /?{somerandomnumber} at the end of my string every time I wanted a reRender and wanted to dispatch the action here is how I edited my reducer to work around this:

case "SET_CURRENT_USER":
      return {
        name: action.name,
        lastname: action.lastname,
        number: action.number,
        email: action.email,
        isAuth: true,
        id: action._id,
        avatar: `http://localhost:3001/users/${
          action._id
        }/avatar/?${moment().valueOf()}`,
      };
Related