I am using React with apollo-client.
If user not the owner of note it should be redirected. But after redirecting I am receiving: Warning: Cannot update a component ('BrowserRouter') while rendering a different component ('EditNote'). To locate the bad setState() call inside 'EditNote'
.
As I can understand problem in useState()
of <NoteForm/>
component. What I do wrong?
import React, { useEffect } from "react";
import { useMutation, useQuery } from "@apollo/client";
import { useNavigate, useParams } from "react-router-dom";
import NoteForm from "../components/NoteForm";
import { GET_NOTE, GET_ME } from "../gql/query";
import { EDIT_NOTE } from "../gql/mutation";
const EditNote = () => {
const navigate = useNavigate();
const params = useParams();
const id = params.id;
const [editNote] = useMutation(EDIT_NOTE, {
variables: {
id
},
onCompleted: () => {
navigate(`/note/${id}`, { replace: true });
}
});
const { loading: noteLoading, error: noteError, data: noteData } = useQuery(GET_NOTE, { variables: { id } });
const { loading: userLoading, error: userError, data: userData } = useQuery(GET_ME);
if (noteLoading || userLoading) return 'Loading...';
if (noteError || userError) return `Error! ${error.message}`;
if (userData.me.id !== noteData.note.author.id) {
navigate(`/note/${id}`, { replace: true });
}
return <NoteForm content={noteData.note.content} action={editNote} />;
};
export default EditNote;
If wrap redirect with useEffect()
will receive error Uncaught TypeError: Cannot read properties of undefined (reading 'me')
as requests was not finished. So maybe I should somehow 'wait' until requests will be not finished or somehow join requests in one useQuery()
.
const { loading: noteLoading, error: noteError, data: noteData } = useQuery(GET_NOTE, { variables: { id } });
const { loading: userLoading, error: userError, data: userData } = useQuery(GET_ME);
useEffect(() => {
if (userData.me.id !== noteData.note.author.id) {
navigate(`/note/${id}`, { replace: true });
}
}, [userData, noteData]);
if (noteLoading || userLoading) return 'Loading...';
if (noteError || userError) return `Error! ${error.message}`;
return <NoteForm content={noteData.note.content} action={editNote} />;
This is NoteForm component, where is useState().
import React, { Component, useState } from "react";
import styled from 'styled-components';
import Button from './Button';
const Wrapper = styled.div`
height: 100%;
`;
const Form = styled.form`
height: 100%;
`;
const TextArea = styled.textarea`
width: 100%;
height: 90%;
`;
const NoteForm = props => {
const [value, setValue] = useState({ content: props.content || '' });
const onChange = event => {
setValue({
...value,
[event.target.name]: event.target.value
});
};
return (
<Wrapper>
<Form onSubmit={e => {
e.preventDefault();
props.action({
variables: { ...value }
});
}}
>
<TextArea required type="text" name="content" placeholder="Note content"
value={value.content}
onChange={onChange}
/>
<Button type="submit">Save</Button>
</Form>
</Wrapper>
);
};
export default NoteForm;