Hang Ngo
Hang Ngo

Reputation: 1

Redux connected React component not updating until a GET api request is recalled

My react app uses a redux connected component to render data from backend for a project page, so I called a GET dispatch inside a React Hook useEffect to make sure data is always rendered when the project page first open, and whenever there is a change in state project, the component will be updated accordingly using connect redux function. However, the component doesn't update after I reduce the new state using a DELETE API request, only if I dispatch another GET request then the state will be updated. So I have to call 2 dispatches, one for DELETE and one for GET to get the page updated synchronously (as you can see in handleDeleteUpdate function), and the same thing happened when I dispatch a POST request to add an update (in handleProjectUpdate). Only when I reload the page, the newly changed data will show up otherwise it doesn't happen synchronously, anyone knows what's wrong with the state update in my code? and how can I fix this so the page can be loaded faster with only one request?

I've changed the reducer to make sure the state is not mutated and is updated correctly. I have also tried using async function in handleDeleteUpdate to make sure the action dispatch is finished

I have tried

console.log(props.project.data.updates)

to print out the updates list after calling props.deleteUpdate but it seems the updates list in the state have never been changed, but when I reload the page, the new updates list is shown up

Here is the code I have for the main connected redux component, actions, and reducers file for the component

function Project(props) {
    let options = {year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit'}
    const {projectID} = useParams();
    const history = useHistory(); 
    console.log(props.project.data? props.project.data.updates : null);
    console.log(props.project.data);
    // const [updates, setUpdates] =  useState(props.project.data? props.project.data.updates : null)
    useEffect(() => {
        props.getProject(projectID);
    }, []);
    
    // Add an update to project is handled here
    const handleProjectUpdate = async (updateInfo) => {
        await props.postProjectUpdate(projectID, updateInfo)
        await props.getProject(projectID);
        

    }
   

    const handleDeleteUpdate = async (updateID) => {
        await props.deleteUpdate(projectID, updateID);
        
        await props.getProject(projectID);
        console.log(props.project.data.updates);
    };

    return (
        <div>
            
            <Navbar selected='projects'/>  
            <div className = "project-info-layout">
                
                     <UpdateCard
                         updates = {props.project.data.updates}
                         handleProjectUpdate = {handleProjectUpdate}
                         handleDeleteUpdate = {handleDeleteUpdate}
                         options = {options}
                        
                     />

               </div>
         
        </div>
        
    )
}

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

export default connect(
    mapStateToProps, 
    {getProject, postProjectUpdate, deleteUpdate}
)(Project);

ACTION

import axios from 'axios';
import { GET_PROJECT_SUCCESS,ADD_PROJECT_UPDATE_SUCCESS, DELETE_PROJECT_UPDATE_SUCCESS} from './types';


let token = localStorage.getItem("token");

const config = {
    headers: {
        Authorization: `Token ${token}`,
    }
};
export const getProject = (slug) => dispatch => {
    axios.get(`${backend}/api/projects/` + slug, config)
        .then(
            res => {
                dispatch({
                    type: GET_PROJECT_SUCCESS,
                    payload: res.data,
                });                
            },
        ).catch(err => console.log(err));
}



export const postProjectUpdate = (slug, updateData) => dispatch => {
    axios.post(`${backend}/api/projects/`+slug+ `/updates`,updateData, config)
        .then(
            res => {
                dispatch({
                    type: ADD_PROJECT_UPDATE_SUCCESS,
                    payload: res.data,
                });
            },
        ).catch(err => console.log(err));
}

export const deleteUpdate = (slug, updateID) => dispatch => {
    axios.delete(`${backend}/api/projects/`+ slug + `/updates/`+ updateID, config)
        .then(
            res => {
                dispatch({
                    type: DELETE_PROJECT_UPDATE_SUCCESS,
                    payload: updateID,
                });
            },
        ).catch(err => console.log(err));
}

Reducer

 import { GET_PROJECT_SUCCESS,ADD_PROJECT_UPDATE_SUCCESS, DELETE_PROJECT_UPDATE_SUCCESS} from "../actions/types";

const initialState = {
  project: {},

};

export default function ProjectReducer(state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case GET_PROJECT_SUCCESS:
      return { 
        ...state, // return all initial state
        project: payload
      };
    
    
    
    case ADD_PROJECT_UPDATE_SUCCESS:
      return {
        ...state,
        project: {
          ...state.project,
          updates: [...state.project.data.updates, payload.data]
        }
      };
    case DELETE_PROJECT_UPDATE_SUCCESS:
      let newUpdatesArray = [...state.project.updates]
      newUpdatesArray.filter(update => update.uuid !== payload) 
      return {
        ...state,
        project: {
          ...state.project,
          members: newUpdatesArray
        }
      };
    
    default:
      return state;
  }
}

updateCard in the Project component is showing a list of all updates

Upvotes: 0

Views: 83

Answers (0)

Related Questions