Reputation: 801
I can't get reducer to return updated state. It returns the updated state with correct info on 2nd time button click. workflow
is the state which has tasks: []
, taskId: ''
and hasError
variable. On button click I call onUnassign
dispatch action which returns an error to invoke WORKFLOW_VALIDATION_DATA_ERROR
reducer action which updates state variable hasError
to true but hasError
displays true on 2nd button click. I'm not able to figure it out why? Below is my code:
const DisActionConnected: React.FC = () => {
const dispatch = useDispatch();
const {tasks, workflow} = useSelector((state: IRootState) => state.workflow);
const onUnassign = () => {
if (tasks && tasks.length > 0) {
dispatch(setUnassign(name));
console.log(workflow) // here hasError is true on 2nd time not first time
}
};
return (
<div>
<DisActions
userId={userId}
onUnassign={onUnassign}
/>
</div>
);
};
store action
export const setUnassign = (name: string) => {
return {
type: TASK_UNASSIGN_PENDING,
payload: {
name
}
}
};
reducer function
export function workflowReducer(
state: IWorkflowState = initialState,
action: WorkflowActionsType
): IWorkflowState {
switch(action.type) {
case WORKFLOW_VALIDATION_DATA_ERROR:
return {...state, hasError: true};
case TASK_UNASSIGN_PENDING:
return {...state};
default:
return {...state};
};
}
STATE
export interface IWorkflowState {
tasks: ITask[];
taskId: string;
hasError: boolean | null
};
const initialState: IWorkflowState = {
tasks: [],
taskId: '',
hasError: false
};
export function* setUnassignDis() {
const errorMessage = "error saving data"
yield put({
type: WORKFLOW_VALIDATION_DATA_ERROR,
payload: {errorMessage}
});
}
function* workflowSaga() {
yield takeEvery(WorkflowStore.TASK_UNASSIGN_PENDING, setUnassignDis);
}
Upvotes: 1
Views: 44
Reputation: 202979
React state updates are not instantaneous and this is how Javascript closures work. workflow
can never be anything but what the workflow
state value is when onUnassign
is called. The current workflow
value is closed over in callback scope. When the button is clicked again and the onUnassign
callback is called it closes over the updated state from the previous update.
If you want to log updated state values then use the useEffect
hook with appropriate dependency.
Example:
const {
tasks,
workflow
} = useSelector((state: IRootState) => state.workflow);
// Log when workflow state updates
React.useEffect(() => {
console.log(workflow);
}, [workflow]);
const onUnassign = () => {
if (tasks?.length) {
dispatch(setUnassign(name));
}
};
...
Upvotes: 1