Redux状态未更新问题:提交表单后新帖子无法显示
Redux Toolkit提交表单后状态未更新的问题排查与解决
我在使用Redux Toolkit开发时,postAdded reducer中通过push方法向state添加新帖子。提交表单后,控制台能打印出action.payload(例如Object { id: "rTuWGH9pfK-cQvCZecSvt", title: "asd", content: "asd" }),但新帖子并未显示在PostList组件中,请问为何状态没有更新?
相关代码
App.js
function App() { return ( <main> <AddPostForm /> <PostList /> </main> ); }
store.js
export const store = configureStore({ reducer: { posts: postsReducer } })
postSlice.js
const initialState = [ { id: 1, title: 'Learning Redux Toolkit', content: 'I have heard good things.' }, { id: 2, title: 'Slices...', content: 'The more I say slice, the more I want pizza.' } ]; const postsSlice = createSlice({ name: 'posts', initialState, reducers: { postAdded: (state, action) => { console.log(action.payload) state.push(action.payload); } } }); export const selectAllPosts = state => state.posts; export const { postAdded } = postsSlice.actions; export default postsSlice.reducer;
AddPostForm.js
function AddPostForm() { const dispatch = useDispatch(); const [title, setTitle] = useState(''); const [content, setContent] = useState(''); function onSubmit() { if (title && content) { console.log('after if'); dispatch(postAdded({ id: nanoid(), title, content })); setTitle(''); setContent(''); } } return ( <section onSubmit={onSubmit}> <h2>Add New Post</h2> <form> <label htmlFor="title">Post Title:</label> <input type="text" id="title" value={title} onChange={e => setTitle(e.target.value)} /> <label htmlFor="content">Content:</label> <textarea id="content" value={content} onChange={e => setContent(e.target.value)} /> <button>Save Post</button> </form> </section> ) } export default AddPostForm
PostList.js
function PostList() { const posts = useSelector(selectAllPosts); return ( <section> <h2>Posts</h2> {posts.map(post => ( <article key={post.id}> <h3>{post.title}</h3> <p>{post.content.substring(0, 100)}</p> </article> ))} </section> ) } export default PostList
问题根源
问题出在表单的默认提交行为:
- 你把
onSubmit绑定在了<section>元素上,但<form>本身的默认提交事件没有被阻止。 - 点击
<button>时,按钮默认类型为submit,会触发<form>的默认提交动作,导致页面刷新,Redux store状态被重置为初始值,所以新添加的帖子无法保留显示。
修复方案
方案一:阻止form默认提交行为
修改AddPostForm.js,将onSubmit绑定到<form>上,并在函数中调用preventDefault()阻止页面刷新:
function AddPostForm() { const dispatch = useDispatch(); const [title, setTitle] = useState(''); const [content, setContent] = useState(''); // 接收事件参数,阻止默认提交 function onSubmit(e) { e.preventDefault(); if (title && content) { dispatch(postAdded({ id: nanoid(), title, content })); setTitle(''); setContent(''); } } return ( <section> <h2>Add New Post</h2> {/* 将onSubmit绑定到form元素 */} <form onSubmit={onSubmit}> <label htmlFor="title">Post Title:</label> <input type="text" id="title" value={title} onChange={e => setTitle(e.target.value)} /> <label htmlFor="content">Content:</label> <textarea id="content" value={content} onChange={e => setContent(e.target.value)} /> <button>Save Post</button> </form> </section> ) }
方案二:修改按钮类型为button
将按钮的type设置为button,避免触发form默认提交,直接绑定点击事件:
function AddPostForm() { const dispatch = useDispatch(); const [title, setTitle] = useState(''); const [content, setContent] = useState(''); function handleSave() { if (title && content) { dispatch(postAdded({ id: nanoid(), title, content })); setTitle(''); setContent(''); } } return ( <section> <h2>Add New Post</h2> <form> <label htmlFor="title">Post Title:</label> <input type="text" id="title" value={title} onChange={e => setTitle(e.target.value)} /> <label htmlFor="content">Content:</label> <textarea id="content" value={content} onChange={e => setContent(e.target.value)} /> {/* 设置按钮类型为button,绑定点击事件 */} <button type="button" onClick={handleSave}>Save Post</button> </form> </section> ) }
修复后,点击保存按钮不会触发页面刷新,Redux store状态会正确更新,PostList组件会通过useSelector感知到状态变化并重新渲染,显示新添加的帖子。
内容的提问来源于stack exchange,提问作者milanHrabos
相关产品推荐
相关产品推荐

