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

React-Redux中useDispatch更新状态后useSelector未触发组件更新

问题原因

两个错误直接导致useSelector订阅失效,和不可变更新、Immer逻辑无关:

  • 取数路径完全错误。你在configureStore里把pagesReducer挂载到了pagesInfo字段下,也就是说slice里的currentElementId、currentPage、pages全在state.pagesInfo命名空间下,根state没有直接暴露这些属性。你代码里所有useSelector(state => state.currentElementId)取到的永远是undefined,根本没有订阅到实际存储值的状态节点,useSelector做===比较时永远拿到undefined,判定状态没变化,自然不会触发重渲染。
  • 违反React Hooks调用规则。你在App组件内嵌套的普通函数GetPageContent里调用了useSelector,Hooks只能在函数组件顶层、自定义Hook顶层调用,写在嵌套普通函数里会导致Hook调用顺序错乱,订阅逻辑完全不生效。

你在Redux DevTools里能看到值更新是正常的,DevTools直接读取store全量状态,不受组件侧订阅逻辑错误的影响,之前尝试手动返回新状态对象没用,因为问题根本不在状态更新环节。

修复方法
  1. 修正所有useSelector的取数路径,所有slice状态都从state.pagesInfo下读取,不要直接从根state取slice内部字段。
  2. 把所有嵌套在普通函数、条件判断、循环里的useSelector移到App组件顶层,严格遵守Hooks调用规则。

修正后的核心代码结构如下:

function App(props) {
  // 所有Hook统一放组件最顶层,路径修正正确
  const dispatch = useDispatch();
  const currentElementId = useSelector(state => state.pagesInfo.currentElementId);
  const currentPage = useSelector(state => state.pagesInfo.currentPage);
  const rawPageLinesContent = useSelector(state => state.pagesInfo.pages[currentPage].lines);
  
  console.log(currentElementId);

  const changeElementID = event => {
    const target = event.target.closest("li")
    if (target) {
      const elementID = target.getAttribute("elementid");
      dispatch(changeCurrentElementID(elementID));
    }
  }

  // 内部渲染函数不再调用Hook,直接使用顶层取到的状态
  const renderPageContent = () => {
    return rawPageLinesContent.map(line => {
      return (
        <ul key={line.id} className={css["page-line"]}>
          {
            line.content.map(element => {
              let finalElement;
              if (element.type == "symbol") {
                const style = { fontSize: element.fontSize + "px" }
                finalElement = (
                  <li onClick={changeElementID} key={element.id} elementid={element.id} className={`${css["page-line__item"]} ${css["page-line__symbol"]}`} style={style}>{element.symbol}</li>
                )
                if (currentElementId == element.id) {
                  finalElement = (
                    <input key={element.id} elementid={element.id} maxLength="1" className={`${css["page-line__item"]} ${css["page-line__symbol"]} ${css["page-line__choosen"]}`} style={style} value={element.symbol} />
                  )
                }
              }
              else if (element.type == "image") {
                finalElement = (
                  <li onClick={changeElementID} key={element.id} elementid={element.id} className={`${css["page-line__item"]} ${css["page-line__image"]}`}>
                    <img src={element.imageSrc} width={element.width} height={element.height} alt="image" />
                  </li>
                )
              }
              return finalElement;
            })
          }
        </ul >
      )
    })
  }

  return (
    <div className={css["App"]}>
      <header className={`${css['App__header']} ${css['tools']} `}>
        <EnterImageButton />
        <TextSizing />
        <TextDecoration />
        <TextAligning />
        <div>{currentElementId || 0}</div>
      </header >
      <div className={`${css['App__content']} ${css['pages']} `}>
        <div className={`${css['pages__item']}`} >
          {renderPageContent()}
        </div>
      </div>
    </div >
  );
}

内容的提问来源于stack exchange,提问作者Aogava

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:36:07