javascript - 为什么我的 React 组件不会在 Redux 存储状态发生变化时重新渲染?

标签 javascript reactjs react-redux

我正在学习 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确实改变了,但在渲染时<div className="UpperTitle"> {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.

最佳答案

在组件中调用 store.getState 不会使其订阅任何更改,它只是获取一次状态,仅此而已。需要发生其他事情才能触发 Layout 组件重新渲染,以便再次调用 store.getState

但这不是我们在 React 组件中订阅存储的方式。您可以使用 connect高阶组件,或更现代的useSelector钩子(Hook)。

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"));

关于javascript - 为什么我的 React 组件不会在 Redux 存储状态发生变化时重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75563415/

相关文章:

javascript - 使用数字格式化文本框 OnfocusOut/OnBlur

javascript - 无法使用 React Native 中的对象访问数组中的值

reactjs - 如何在React Native Redux组件中添加错误处理?

javascript - 如何在博览会中选择多个图像

javascript - 如果您不想更改值,如何将默认值作为输入值传回?

javascript - 如何将 printThis 插件功能分配给按钮?

javascript - 按比例缩放图像以适合其父对象

javascript - 在 TypeScript 中扩展功能

javascript - 列表中的每个 child 都应该有唯一的 'key' prop

javascript - 使用 ReactJS 构建时,Chrome 扩展内容脚本不会注入(inject) DOM