You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:43:29