用按钮反应更新状态只更新一次状态

React update state with button only updates state once

我在我的博客组件中添加了一个赞按钮,并且状态在后端更新,但它只发生一次。一旦我按下 'like' 按钮,'likes' 计数的状态就会增加 1,但每次使用类似按钮进行的​​调用都会发出 PUT 请求,但不会增加计数。

App.js

import blogService from './services/blogs';
...

const App = () => {
  // All blogs display
  const [blogs, setBlogs] = useState([]);
  ....

  const updateBlog = async blogObject => {
    const updatedBlog = await blogService.update(blogObject.id, blogObject);
    setBlogs(
      blogs.map(blog => (blog.id !== updatedBlog.id ? blog : updatedBlog)),
    );
    console.log(updatedBlog);
    setMessage(`Liked "${updatedBlog.title}"`);
    setMessageClass('success');
    setTimeout(() => {
      setMessage(null);
      setMessageClass('none');
    }, 3000);
  };

...

return (
    <div>
      <Container>
        <p className={messageClass}>{message}</p>

        <p>{user.name} is logged in </p>
        {logOutForm()}
        <hr />
        <br />
        {blogForm()}
        <hr />
        <ul>
          {blogs.map(blog => (
            <Blog key={blog.id} blog={blog} updateBlog={updateBlog} />
          ))}
        </ul>
      </Container>
    </div>
  );

blogs.js(博客服务)

import axios from 'axios';
const baseUrl = '/api/blogs';

....

const update = (id, newObject) => {
  const request = axios.put(`${baseUrl}/${id}`, newObject);
  return request.then(response => response.data);
};

Blog.js分量

const Blog = ({ blog, updateBlog }) => {
  ...

  const [blogObject, setBlogObject] = useState(blog);

  const likeBlog = () => {
    let likes = blog.likes + 1;
    // Make a copy of the blog object and pass new likes count
    const editedBlog = { ...blog, likes };
    updateBlog(editedBlog);
    setBlogObject(editedBlog);
  };

  return (
    <div>
      <ListGroup variant className='m-3'>
        <div style={hideWhenVisible}>
          <ListGroup.Item>{blog.title} </ListGroup.Item>
          <Button
            onClick={toggleVisibility}
            style={buttonStyle}
            variant='primary'
          >
            View
          </Button>
        </div>
        <div style={showWhenVisible}>
          <ListGroup.Item>{blog.title} </ListGroup.Item>
          <ListGroup.Item>{blog.url}</ListGroup.Item>
          <ListGroup.Item>{blog.author}</ListGroup.Item>
          <ListGroup.Item>
            <Button
              variant='success'
              type='submit'
              style={{ marginLeft: '8px' }}
              onClick={likeBlog}
            >
              {blogObject.likes} likes
            </Button>
          </ListGroup.Item>
          <Button
            onClick={toggleVisibility}
            style={buttonStyle}
            variant='secondary'
          >
            Hide
          </Button>
        </div>
        <hr style={hrStyle} />
      </ListGroup>
    </div>
  );
};

Blogs.js(后端的控制器文件夹)

blogsRouter.put('/:id', async (request, response, next) => {
  const body = request.body;

  const blog = {
    author: body.author,
    title: body.title,
    url: body.url,
    likes: body.likes,
  };

  try {
    // Update command
    const editedBlog = await Blog.findByIdAndUpdate(request.params.id, blog, {
      new: true,
    });
    editedBlog.toJSON();
  } catch (exception) {
    next(exception);
  }
});

每次按下 'Like' 按钮时控制台

---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---

你在控制台上面看到每次都发出一个PUT请求,但是'Likes'没有递增。

据我所知,您需要在 Blog 组件中添加一个 useEffect 挂钩,以便在更改后再次读取 blog,例如:

useEffect(() => {
  setBlogObject(blog)
}, [blog]);

这将更新 likes 计数,因为它来自您对更新调用的 API 响应,但是,从我自己的角度来看,您可以直接依赖 blog 属性 在 Blog 组件上,只需计算 运行 上的任何其他值,而不需要使用状态挂钩停止。

===========

更新 #1

另一种方法是将 blog 引用更新为最新的引用(您存储在博客的组件状态中)。

  const likeBlog = () => {
    let likes = blogObject.likes + 1;
    // Make a copy of the blog object and pass new likes count
    const editedBlog = { ...blogObject, likes };
    updateBlog(editedBlog);
    setBlogObject(editedBlog);
  };