用按钮反应更新状态只更新一次状态
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);
};
我在我的博客组件中添加了一个赞按钮,并且状态在后端更新,但它只发生一次。一旦我按下 '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);
};