【问题标题】:React component won't update react-reduxReact 组件不会更新 react-redux
【发布时间】:2021-11-15 06:23:06
【问题描述】:

我有一个导航栏组件,其中包含一个下拉菜单,允许用户更改他们的“区域”并更新 redux 存储。对 redux 商店的更新工作正常。但是,它不会重新渲染父组件。

在这个导航栏组件中,我使用 changeRegion ActionCreator 来更新商店。我可以在 localstorage 中看到更新,甚至可以对其进行 console.log 并在更改后查看正确的区域。没有发生的是,“UserManagement”组件中的表没有更新。

我在 UserManagement.js 中的 useEffect() 中使用 setPageData 来确定表处于什么状态。基本上,如果没有选择区域(initialState 为空白),那么它应该显示一个带有下拉列表的空表以供选择地区。一旦选择了一个区域,它就应该在表格中显示数据。

很明显,我只是遗漏了一些东西,但我一直在努力让这项工作完成太久,真的需要一些帮助。

用户管理.js

import React, { useState, useEffect } from "react";
import {
  Box,
  ButtonDropdown,
  Table,
} from "private-compontent";
import fakeData from "../fakeData"

import { useSelector, useDispatch } from 'react-redux'
import { bindActionCreators } from 'redux'
import { actionCreators } from '../../../state/actionsCreators'

export const DetailsTable = (props) => {
 
  const [pageData, setPageData] = useState([]);
  const region = useSelector((state) => state.region)
  const dispatch = useDispatch();
  const { changeRegion } = bindActionCreators(actionCreators, dispatch)
  const [regionState, setRegionState] = useState(region);
  const currentUserRegion = region === '' ? "Select Region" : "Region: " + region;  
  

  useEffect(() => {
    if (region && region !== '') {
      setRegionState(region)
      setPageData(fakeData);
    } else {
      setPageData([{}]);
    }
  }, []);


    // When a new region is selected, save it to localStorage and setRegion
    const regionChange = (event) => {
      changeRegion(event.detail.id)
    }

  function EmptyState({ title, subtitle, action }) {
    return (
      <Box textAlign="center" color="inherit">
        <Box variant="strong" textAlign="center" color="inherit">
          {title}
        </Box>
        <Box variant="p" padding={{ bottom: 's' }} color="inherit">
          {subtitle}
        </Box>
        {action}
      </Box>
    );
  }
  
  return (
    <>
      <Table
        {...collectionProps}
        items={ items }
        empty={
          <EmptyState
          title="No Data"
          subtitle="No data to display"
          action={
            <ButtonDropdown
              items={[
                  { text: "NA", id: "NA", disabled: false },
                  { text: "EU", id: "EU", disabled: false },
                  { text: "FE", id: "FE", disabled: false },
              ]}
              onItemClick={regionChange}
            >
            {currentUserRegion}
          </ButtonDropdown> }
        />
        }
      />
    </>
  );
};

export default DetailsTable;

Navbar.js

import React from "react";
import { ButtonDropdown} from "../ButtonDropdown";
import { useSelector, useDispatch } from 'react-redux'
import { bindActionCreators } from 'redux'
import { actionCreators } from '../../../state/actionsCreators'


export const Navbar = () => {
    const region = useSelector((state) => state.region)
    const dispatch = useDispatch();
    const { changeRegion } = bindActionCreators(actionCreators, dispatch)

    // When a new region is selected, save it to localStorage and setRegion
    const regionChange = (event) => {
        changeRegion(event.detail.id)
    }

    const currentUserRegion = region === '' ? "Select Region" : "Region: " + region;
    // Construct the ButtonDropdown based on the currentPath
    const regionButtonDropdown = 
        // If UserManagement show region options
            <ButtonDropdown
                items={[
                    { text: "NA", id: "NA", disabled: false },
                    { text: "EU", id: "EU", disabled: false },
                    { text: "FE", id: "FE", disabled: false },
                ]}
                onItemClick={regionChange} // Run regionChange on dropdown change
            >
                {currentUserRegion}
            </ButtonDropdown> 

    // Return our HTML
    return (
        <>
            <header id="navbar">
                {regionButtonDropdown}
            </header>
        </>
    );
};

export default Navbar;

reducers.js

import { combineReducers } from "redux"
import regionReducer from "./regionReducer"

const reducers = combineReducers({
    region: regionReducer
})

export default reducers;

regionReducer.js

import * as ACTIONS from '../actionsTypes'

const initialState = '';
const reducer = (state = initialState, action) => {
    switch (action.type) {
        case ACTIONS.CHANGE_REGION:
            return action.payload;
        default: 
            return state;
    }
}

export default reducer;

store.js

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import logger from 'redux-logger';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

import rootReducer from './reducers/reducers'

const persistConfig = {
    key: 'root',
    storage
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

const middleware = applyMiddleware(thunk, logger);
const store = createStore(
    persistedReducer, 
    middleware
);

const persistor = persistStore(store);

export { store, persistor };

【问题讨论】:

    标签: reactjs redux react-redux redux-thunk


    【解决方案1】:

    您的useMemo 仅在页面加载时运行。改成

    useEffect(() => {
        if (region && region !== '') {
          setRegionState(region)
          setPageData(fakeData);
        } else {
          setPageData([{}]);
        }
      }, [region]);
    

    这样它就在region 更改时运行。请参阅 React 文档中的 Conditionally firing an effect

    特别注意,

    如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉 React 你的效果不依赖于任何来自 props 或 state 的值,所以它永远不需要重新运行。

    【讨论】:

    • 非常有帮助,谢谢
    • 很高兴我能帮上忙。其他需要考虑的是,您也可以尝试在regionChange 处理程序中调用setRegionStatesetPageData,而不是useEffect
    猜你喜欢
    • 2016-06-30
    • 2018-04-08
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2023-03-28
    相关资源
    最近更新 更多