BranOIE
BranOIE

Reputation: 430

React can't read value gotten from Redux state

Bit of a weird one. In my component I am getting a "task" object from my "taskDetails" reducer. Then I have a useEffect function that checks if the task.title is not set, then to call the action to get the task.

However when the page loads I get an error cannot read property 'title' of null which is strange because when I look in my Redux dev tools, the task is there, all its data inside it, yet it can't be retrieved.

Here is the relevant code:

    const taskId = useParams<{id: string}>().id;

    const dispatch = useDispatch();
    const history = useHistory();

    const [deleting, setDeleting] = useState(false)

    const taskDetails = useSelector((state: RootStateOrAny) => state.taskDetails);
    const { loading, error, task } = taskDetails;

    const successDelete = true;

    const deleteTaskHandler = () => {

    }

    useEffect(() => {
        if(!successDelete) {
            history.push('/home/admin/tasks')
        } else {
            if(!task.title || task._id !== taskId) {
                dispatch(getTaskDetails(taskId))
            } 
        }
    },[dispatch, task, taskId, history, successDelete])

REDUCER

  export const taskDetailsReducer = (state = { task: {} }, action) => {
    switch(action.type) {
      case TASK_DETAILS_REQUEST:
        return { loading: true }
      case TASK_DETAILS_SUCCESS:
        return { loading: false, success: true, task: action.payload }
      case TASK_DETAILS_FAIL:
        return { loading: false, error: action.payload }
      case TASK_DETAILS_RESET:
        return { task: {} }
      default:
        return state 
    }
  }

ACTION

  export const getTaskDetails = id => async (dispatch) => {
    try {
      dispatch({
        type: TASK_DETAILS_REQUEST
      })

      const { data } = await axios.get(`http://localhost:5000/api/tasks/${id}`) 

      dispatch({
        type: TASK_DETAILS_SUCCESS,
        payload: data
      })

    } catch (error) {
      dispatch({
        type: TASK_DETAILS_FAIL,
        payload:
          error.response && error.response.data.message
            ? error.response.data.message
            : error.message
      })
    }
  }

Upvotes: 0

Views: 51

Answers (1)

BranOIE
BranOIE

Reputation: 430

In my reducer in the TASK_DETAILS_REQUEST case, I just had loading: false.

I had failed to specify the original content of the state, I did this by adding ...state.

   export const taskDetailsReducer = (state = { task: {} }, action) => {
    switch(action.type) {
      case TASK_DETAILS_REQUEST:
        return { ...state, loading: true }
      case TASK_DETAILS_SUCCESS:
        return { loading: false, success: true, task: action.payload }
      case TASK_DETAILS_FAIL:
        return { loading: false, error: action.payload }
      case TASK_DETAILS_RESET:
        return { task: {} }
      default:
        return state 
    }
  }

Upvotes: 1

Related Questions