React 组件不会更新 react-redux
React component won't update react-redux
我有一个导航栏组件,其中包含一个下拉列表,允许用户更改他们的“区域”并更新 redux 存储。 redux store 的更新工作正常。但是,它并没有重新渲染父组件。
在这个导航栏组件中,我使用 changeRegion ActionCreator 来更新商店。我可以在 localstorage 中看到更新,甚至可以 console.log 它并在更改后看到正确的区域。没有发生什么,是“UserManagement”组件中的 table 没有更新。
我用setPageData
in useEffect()
in UserManagement.js来判断table处于什么状态。基本上,如果没有区域selected (initialState 为空白)然后它应该显示一个空的 table,下拉菜单指向 select 区域。一旦一个区域被 selected,它应该在 table.
中显示数据
显然我只是遗漏了一些东西,但我一直在努力使这项工作太久,真的需要一些帮助。
UserManagement.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 };
您的 useMemo
仅在页面加载时运行。改成
useEffect(() => {
if (region && region !== '') {
setRegionState(region)
setPageData(fakeData);
} else {
setPageData([{}]);
}
}, [region]);
以便它在 region
更改时运行。请参阅 React 文档中的 Conditionally firing an effect。
特别说明,
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.
我有一个导航栏组件,其中包含一个下拉列表,允许用户更改他们的“区域”并更新 redux 存储。 redux store 的更新工作正常。但是,它并没有重新渲染父组件。
在这个导航栏组件中,我使用 changeRegion ActionCreator 来更新商店。我可以在 localstorage 中看到更新,甚至可以 console.log 它并在更改后看到正确的区域。没有发生什么,是“UserManagement”组件中的 table 没有更新。
我用setPageData
in useEffect()
in UserManagement.js来判断table处于什么状态。基本上,如果没有区域selected (initialState 为空白)然后它应该显示一个空的 table,下拉菜单指向 select 区域。一旦一个区域被 selected,它应该在 table.
显然我只是遗漏了一些东西,但我一直在努力使这项工作太久,真的需要一些帮助。
UserManagement.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 };
您的 useMemo
仅在页面加载时运行。改成
useEffect(() => {
if (region && region !== '') {
setRegionState(region)
setPageData(fakeData);
} else {
setPageData([{}]);
}
}, [region]);
以便它在 region
更改时运行。请参阅 React 文档中的 Conditionally firing an effect。
特别说明,
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.