I am kind of running my head into a wall on a weird circumstance using the React Context API along with the useReducer and useContext hooks.
Here is my main store.
import React, { createContext, useReducer } from 'react';
import { Reducers } from './Reducers';
import { surveys } from '../../testData.json';
export const context = createContext();
const { Provider } = context;
export const Store = ({ children }) => {
const [store, dispatch] = useReducer(Reducers, {
editSurvey: { display: false },
surveys,
});
return <Provider value={{ store, dispatch }}>{children}</Provider>;
};
Here is my Reducers function and my Action types:
import { Actions } from './Actions';
const { DISPLAY_NEW_SURVEY, HIDE_SURVEY } = Actions;
export const Reducers = (state, action) => {
const { type, payload } = action;
console.log(state, action);
switch (type) {
case DISPLAY_NEW_SURVEY:
return { ...state, editSurvey: { display: true } };
case HIDE_SURVEY:
return { ...state, editSurvey: { display: false } };
default:
return state;
}
};
export const Actions = {
DISPLAY_NEW_SURVEY: 'DISPLAY_NEW_SURVEY',
HIDE_SURVEY: 'HIDE_SURVEY',
};
I have a display property inside my edit property which is used to conditionally render a react portal, see below:
import React, { useContext } from 'react';
import { EditSurveyPortal } from '../EditSurvey/EditSurveyPortal';
import { context } from '../../store/Store';
export const NavItem = ({ name, NavImage }) => {
const { dispatch } = useContext(context);
return (
<div
id={name}
style={{ cursor: 'pointer' }}
onClick={() => {
dispatch({ type: 'DISPLAY_NEW_SURVEY' });
}}
>
<NavImage alt={name} width={10} height={10} />
<EditSurveyPortal />
</div>
);
};
import React, { useContext } from 'react';
import { createPortal } from 'react-dom';
import { context } from '../../store/Store';
import { EditSurvey } from './EditSurvey';
export const EditSurveyPortal = () => {
const {
store: {
editSurvey: { display },
},
dispatch,
} = useContext(context);
return display
? createPortal(
<div className="absolute top-0 left-0 w-screen h-screen z-10 flex justify-center items-center bg-gray-400 bg-opacity-50">
<EditSurvey />
</div>,
document.getElementById('root'),
)
: null;
};
And here is the actual edit survey component:
import React from 'react';
import { Card, CardHeader } from '../Utility/Card';
import { Close } from '../Images/Close';
export const EditSurvey = ({ dispatch }) => {
return (
<Card>
<CardHeader className="flex justify-between align-center">
<div className="inline-block relative rounded">
<span className="absolute top-0 l-0 bg-gray-200 text-gray-800 rounded-l px-2 py-1">
Title
</span>
<input type="text" className="rounded p-1" />
</div>
<div
className="text-gray-800"
style={{ cursor: 'pointer' }}
onClick={() => {
dispatch({ type: 'HIDE_SURVEY' });
}}
>
<Close width={8} height={8} />
</div>
</CardHeader>
</Card>
);
};
My issue is that when I click the close button on the portal, it dispatches HIDE_SURVEY then immediately dispatches DISPLAY_NEW_SURVEY:
I cannot for the life of me figure this out. Any help would be greatly appreciated.
Thanks!