How to properly edit a value of a put/patch request on react

Viewed 70

I have an edit caption of a post feature on my app. I am fetching a get request and then save that data in a state that will display on screen. The problem here is that it take a few second to load that data on screen. After editing the caption, which I have a onChange function that will update the state with the new edited caption. The new edited caption is followed by a put request that will update the caption of the post. The problem here is that I am getting an error saying to change it to either a controlled or uncontrolled state. What is the right way of doing it?

Edit: For some reason, the error isn't showing on the console now with the same code I had previously without changes. So I guess that problem is fixed? But like I mentioned before, the caption would show up empty and then show the value of the caption 2 seconds after. Is there a way to show it instantly? Im assuming it not possible since It need to make a get request first and then store the data in the state, right?

The error I'm getting

Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.

Below is my code

const PostDetail = () => {
    const navigate = useNavigate();
    const [inputs, setInputs] = useState({ caption: "" });
    const { id } = useParams();

    // once data is fetched, update the edited caption to the post
    useEffect(() => {
        const fetchDetails = async () => {
            const res = await api.get(`/post/${id}`)
                .catch((error) => console.log(error.message))
            const data = await res.data;
            return data;
        }
        fetchDetails()
            .then((data) => {
                setInputs({
                    caption: data.post.caption
                });
            });
    }, [id]);


    const sendRequest = async () => {
        const res = await api.put(`/post/update/${id}`, {
            caption: inputs.caption
        })
            .catch(error => console.log(error));
        const data = await res.data;
        return data;
    }

    const handleSubmit = (e) => {
        e.preventDefault();
        console.log(inputs);
        sendRequest()
            .then((data) => console.log(data))
            .then(() => navigate('/myposts'))
    }

    const handleChange = (e) => {
        setInputs({ caption: e.target.value })
    }

    return (
        <div>
            {inputs &&
                <form onSubmit={handleSubmit}>
                    <Box display="flex" flexDirection="column" alignItems="center" justifyContent="center" boxShadow=" 10px 10px 20px #ccc" maxWidth={500} margin="auto" padding={3} marginTop={10} borderRadius={5}>
                        <Typography fontWeight={"bold"} padding={3} textAlign={"center"} fontSize={22} fontFamily="georgia">Edit Your Post</Typography>
                        <InputLabel sx={{ mb: 1, mt: 2, fontSize: 15 }}>Caption</InputLabel>
                        <TextField value={inputs.caption} name="caption" onChange={handleChange} fullWidth />
                        <Button variant="contained" type="submit" color="warning" sx={{ marginTop: 3 }}>Submit</Button>
                    </Box>
                </form>
            }
        </div>
    )
}
1 Answers

This warning occurs when an input's value switches from null or undefined to a real value or vice-versa.

My guess is that data.post.caption isn't present in the fetch response, so you end up setting the input's value to undefined.

This makes it an uncontrolled input.

Then you type in the field, state gets updated, and you set the input's value to a string, making it a controlled input.

Hence the warning.

If that's the case you could mitigate it by ORing it with an empty string: data.post.caption || "".

Related