【问题标题】:Why does not my react component re-render on redux store state change?为什么我的 React 组件不会在 redux 存储状态更改时重新呈现?
【发布时间】:2023-02-25 13:32:44
【问题描述】:

我说要学习 React 和 Redux,但我无法弄清楚为什么我的 React 组件在 Redux 存储状态更改后不会重新呈现。

这是我的代码:

const initialState = { value: 'Loading...' }

function onSetName(state = initialState, action) {
  if (action.type === 'doc/docnamechanged') {
    return {
      ...state,
      value: action.payload
    }
  }
  return state
}

export const setName = text => {
  return {
    type: 'doc/docnamechanged',
    payload: text
  }
}

export const store = configureStore({ reducer: onSetName })
store.subscribe(() => Layout(), App());

export default function App() {  
  return (
    <Routes>
      <Route element={<Layout />}>
        <Route path="/1" element={<PublicPage />} />
      </Route>
    </Routes>
  )
}

那是我的派遣

  if (store.getState().value != "AD") {
    store.dispatch(setName("AD"));
  }
function Layout() {
  console.log(store.getState().value);

  const name = store.getState().value;

  return (
    <div className="App">
      <div className="header">
        <img className="logo" src="images/logotype.png" alt="logo" />
        <div className="UpperTitle">
          {name}
        </div>
      </div>
    </div>
  )
}

所以我可以在控制台中看到 store.getState().value 确实发生了变化,但在呈现的 &lt;div className="UpperTitle"&gt; {name} 中没有变化。如您所见,我也尝试订阅我的 App() 函数,但这根本没有帮助。感谢任何帮助。

如果我在 index.js 中订阅 render(),我设法让它以某种方式工作,但这似乎是错误的并导致警告消息

react-dom.development.js:86 Warning: Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate.

【问题讨论】:

    标签: javascript reactjs react-redux


    【解决方案1】:

    在组件中调用 store.getState 不会订阅任何更改,它只是获取状态一次,仅此而已。需要发生其他事情来触发 Layout 组件重新呈现,因此将再次调用 store.getState。

    但这不是我们在 React 组件中订阅商店的方式。您可以使用 connect 高阶组件,或更现代的 useSelector 挂钩。

    import { useSelector } from 'react-redux';
    import { Outlet } from 'react-router-dom';
    
    function Layout() {
      const name = useSelector(state => state.value); // <-- subscribe to changes
      
      useEffect(() => {
        console.log({ name });
      }, [name]);
    
      return (
        <div className="App">
          <div className="header">
            <img className="logo" src="images/logotype.png" alt="logo" />
            <div className="UpperTitle">
              {name}
            </div>
          </div>
          <Outlet /> // <-- for the nested routes ?
        </div>
      );
    }
    

    您需要确保将 Redux 商店提供给 React 应用程序。

    import { Provider } from 'react-redux';
    import { configureStore } from '@reduxjs/toolkit';
    
    const initialState = {
      value: 'Loading...'
    };
    
    function onSetName(state = initialState, action) {
      if (action.type === 'doc/docnamechanged') {
        return {
          ...state,
          value: action.payload
        };
      }
      return state;
    }
    
    export const setName = text => ({
      type: 'doc/docnamechanged',
      payload: text,
    });
    
    export const store = configureStore({
      reducer: onSetName,
    });
    
    export default function App() {  
      return (
        <Provider store={store}>
          <Routes>
            <Route element={<Layout />}>
              <Route path="/1" element={<PublicPage />} />
            </Route>
          </Routes>
        </Provider>
      );
    }
    

    因为看起来你是实际上已经在使用 Redux-Toolkit,你应该真正使用当前的 Redux 模式。

    import { Provider } from 'react-redux';
    import { configureStore, createslice } from '@reduxjs/toolkit';
    
    const initialState = {
      value: 'Loading...'
    };
    
    const nameSlice = createSlice({
      name: "name",
      initialState,
      reducers: {
        setName: (state, action) => {
          state.value = action.payload;
        },
      },
    });
    
    export const {
      ...nameSlice.actions,
    };
    
    export const store = configureStore({
      reducer: nameSlice.reducer,
    });
    
    import { setName } from '../path/to/name.slice';
    
    ...
    
    dispatch(setName("AD"));
    

    【讨论】:

      猜你喜欢
      • 2016-12-05
      • 2019-03-11
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多