mern - updated values are null in data

Viewed 477

I'm trying to update the posts. The PUT request in the back end works fine, returning 200 and updates posts when tested on Postman however when I try to update a post in the front end (react), I'm not receiving any errors but the updated post isn't being updated on submit and the updated fields (title and body) are null. The updated values are null when I console.log(data) in the front end which is why they aren't being sent to the back end but they are shown correctly in post. Why are the updated values null inside data? How can I update the post with the new values instead of getting null?

data: data post: post Updated code: Frontend

const EditPost = ({match}) => {
  const [values, setValues] = useState({
    title: "",
    body: "",
    error: ""
  });
  
  const [post, setPost] = useState({});
  const { user, token } = isAuthenticated();
  const {
    title,
    body,
    error,
  } = values;


  const init = (id) => { 
      read(id).then(data => {
if (data.error) {
    setValues({...values, error: data.error})
} else {
    setValues({...values,
         title: data.title,
        body: data.body,
    }) 
    setPost({title: values.title, body: values.body})
     }
    })
}
 

useEffect(() => {
    const id = match.params.id;
  init(id);
}, []);

useEffect(() => {
  setPost({...values });
}, [values.title, values.body]);


  const handleChange = (name) => (event) => {
    setValues({ ...values, [name]: event.target.value });
  };

  const clickSubmit = (event) => {
    event.preventDefault();
    setValues({ ...values, error: "" });

    editPost(match.params.userId, match.params.id, token, post).then((data) => {
      if (data.error) {
        setValues({ ...values, error: data.error });
      } else {
        setValues({
          ...values,
          title: "",
          body: "",
          error: false,
        });      
      console.log(post)
      console.log(data)
      }
    });
  };

  const newPostForm = () => (
    <form onSubmit={clickSubmit}>
      <div>
        <input
          onChange={handleChange("title")} type="text"
          name="title"
          value={title}
        />
      </div>

      <div className="form-group">
        <textarea
          onChange={handleChange("body")}
          value={body} name="body"
        />
      </div>

      <button type="submit">Publish</button>
    </form>
  );
  const showError = () => (
    <div
      style={{ display: error ? "" : "none" }}>
      {error}
    </div>
  );

  return (
        <div>  
          {showError()}
          {newPostForm()}
        </div>
  );
};

export default EditPost;
export const editPost = (userId, id, token, post) => {
    return fetch(`${API}/${userId}/${id}/edit`, {
        method: 'PUT',
        headers: {
            Accept: 'application/json',
            Authorization: `Bearer ${token}`
        },
        body: JSON.stringify(post)
    })
        .then(response => {
            return response.json();
            
        })
        .catch(err => console.log(err));
};

postsByUser.js

 <Link className="mypost_btn edit_btn" to={`/${_id}/${post._id}/edit`}>
     Edit
 </Link>

Backend code

exports.edit = (req, res) => {
  if (!ObjectID.isValid(req.params.id))
        return res.status(400).send(`ID is not valid: ${req.params.id}`)

  const {title, body} = req.body

  const updatedPost = {title, body }

  Post.findByIdAndUpdate(req.params.id, {
    $set: updatedPost
  }, {new:true}, (error, data) => {
    if (error) {
      return error
    } else {
      res.send(data)
      console.log(data)
    }
  })
}
2 Answers

Your problem lies here:

editPost(match.params.userId, match.params.id, token, post)

post is not defined.

Since post is not defined, no data is passed. Hence title and body equal to null. What you will need to do is, assuming from what I'm seeing on your code, is to define a state variable called post. I think you intended to do that:

const [post, setPost] = useState({values.title, values.body});

Then ensure that your post is updated whenever your values change using useEffect(),

useEffect(() => {
   setPost({...values });
}, [values.title, value.body]);

So by the time you call your editPost() http-put-method, then post has a value. And it should work.

in EditPost.js editPost(match.params.userId, match.params.id, token).then((data) => { here you are missing the 4th arg which is the "post" it self you send to be updated

Related