I am using use reducer inside a ReactContext to handle some signatures display. On Messages and messagesForm components the dispatch function works fine. But inside prevMessages it doesn't. I tried console log (json) but it is also not working inside the handleDeleteMes() function. I have tried everything I could think of for solving this problem.
Here I provide my code:
This is the parent component -Messages.jsx:
function Messages() {
const {dispatch, signing, signatures} = useSignatureContext();
const { user } = useUserContext()
const thisPalRef = useRef([]);
useEffect(()=>{
const fetchSignatures = async()=>{
const response = await fetch('/api/signatures/sent', {
method: 'GET',
headers: {
'Authorization': `Bearer ${user.token}`
}
})
const json = await response.json();
if (response.ok) {
json.forEach((mes)=>{
mes.recipient_id === signing._id && thisPalRef.current.push(mes)
})
}
dispatch({type:'SET_SIGNATURES', payload: thisPalRef.current}) //It works fine
}
fetchSignatures()
},[signing._id, user.token, dispatch])
return (
<motion.div
initial= {{opacity: 0, height:'10%',width:'85%', x:0}}
animate= {{opacity: 1, height:'100%', width:'95%', x:0}}
exit= {{opacity:0, height:'10%',width:'85%', x:0}}
transition={{ duration: 0.2 }}>
<div className="d-flex flex-column align-items-start p-1 pt-4">
<MessageForm />
<div className='prevMsg_container d-flex flex-column align-items-end p-3 mb-5'>
<header className='my-5 align-self-center'>
<h2>Previous Messages</h2>
<hr />
</header>
{
signatures ? signatures.map(mes => {
console.log(signatures)
return <PrevMessages key={mes._id} mes={mes}/>
}) : <small className="text-muted">No messages sent</small>
}
</div>
</div>
</motion.div>
)
}
one child component -PrevMessages.jsx
function PrevMessages({mes}) {
const {dispatch} = useSignatureContext();
const {user} = useUserContext();
const handleDeleteMes = async() => {
if (!user) {
return
}
const response = await fetch('/api/signatures/' + mes._id, {
method:'DELETE',
headers: {
'Authorization': `Bearer ${user.token}`
}
})
const json = await response.json();
console.log(json) //it doesn't work
if (response.ok) {
dispatch({type: 'DELETE_SIGNATURE', payload: json}) //it doesnt work
}
}
return <figure className="text-end">
<blockquote className="blockquote">
<p className='prevMsg_text mt-3 text-end'>{mes.message}</p>
</blockquote>
<figcaption className="blockquote-footer text-end">
<cite title="Sent date">{formatRelative (new Date(mes.updatedAt), new Date())}</cite>
</figcaption>
<IconContext.Provider value={{ color: '#ea1537', className: "delete_icon" }}>
<span className="text-end delete_msg_btn" onClick={() => handleDeleteMes(mes._id)}><RiChatDeleteFill/></span>
</IconContext.Provider>
</figure>
}
and another child component -MessageForm.jsx
function MessageForm() {
const {signing, dispatch} = useSignatureContext();
const { user } = useUserContext()
const [myMessage, setMyMessage] = useState('');
const [error, setError] = useState(null);
const [emptyFields, setEmptyFields] = useState([]);
const handleSubmitMessage = async (e) => {
e.preventDefault()
if (!user) {
setError('You must be logged in')
return
}
const mssg = {
message: myMessage,
recipient: `${signing.name} ${signing.last_name}`,
recipient_id: signing._id,
sender: `${user.name} ${user.last_name}`,
sender_id: user._id,
sender_signature: user.signature
}
const response = await fetch('/api/signatures', {
method: 'POST',
body: JSON.stringify(mssg),
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${user.token}`
}
})
const json = await response.json()
if(!response.ok){
setError(json.error)
setEmptyFields(json.emptyFields)
}
if (response.ok) {
setMyMessage('');
setError(null);
setEmptyFields([]);
console.log('new message sent!', json);
dispatch({type: 'CREATE_SIGNATURE', payload: json}); //works fine
}
}
return (
<>
<h1 className='align-self-center bk_owner_title'>{signing.name}<small className="text-muted">'s Book</small></h1>
<div className="input-group">
<textarea value={myMessage} className={"form-control txtArea pt-4 ps-2 msg_txt_area " + (emptyFields.includes('message') ? ' message_error' : '')} autoFocus onChange={(e)=>setMyMessage(e.target.value)} placeholder={'Dear ' + signing.name + ' ' + signing.last_name + '...'}></textarea>
</div>
<figcaption className='message_footer mx-3 mt-1'>From: {user.signature}</figcaption>
<button type='submit' className='btn btn-success align-self-end' onClick={(e)=>handleSubmitMessage(e)}>Send</button>
{error && <Alert variant='danger' className='mt-3 align-self-center alert_message'>{error}</Alert>}
</>
)
}
And this is the context -SignatureContext.jsx
const SignatureContext = createContext();
const signaturesReducer = (mesState, action) => {
switch (action.type) {
case 'SET_SIGNATURES':
return {
signatures: action.payload
}
case 'CREATE_SIGNATURE':
return {
signatures: [action.payload, ...mesState.signatures]
}
case 'DELETE_SIGNATURE':
return {
signatures: mesState.signatures.filter((s) => s._id !== action.payload._id)
}
default:
return mesState
}
}
const SignatureContextProvider = ({children})=> {
const [signing, setSigning] = useState({});
const [mesState, dispatch] = useReducer(signaturesReducer, {
signatures: null
});
return (
<SignatureContext.Provider value={{signing, setSigning, ...mesState, dispatch}}>
{children}
</SignatureContext.Provider>
)
}
export {SignatureContextProvider, SignatureContext, signaturesReducer};
Thank you in advance, any ideas will be appreciated.