【发布时间】:2021-01-24 01:59:36
【问题描述】:
代码很长,但思路是这样的:
我有 3 个组件 Base App 组件、MapComponent、ShipComponent
App 组件使用容器调用 MapComponent,MapComponent 调用 ShipComponent 也使用容器。
Map 和 Ship 容器都连接到 store。
Map 和 Ship 组件使用相同的多数组数据并传递给mapStateToProps
在使用 useEffect() 的组件 Ship 中,调用一个动作来生成数据并将其放入存储中。
问题:
子组件(组件 Ship)重新渲染得很好,但组件 Map(父组件)甚至不使用父 Map 组件也使用相同的 shipLocation 数组。 map 和 Ship 组件都从同一个 redux store 中获取。
为什么子组件在执行动作后会重新渲染而父组件却没有?我该如何解决?
作为测试,我没有将动作通过mapDispatchToProps 传递给 ShipComponent,而是将其传递给 MapComponent 并通过 props 将其传递给 ShipComponent 以使其执行。只有这样它才更新了父 MapComponent。但我需要 ShipComponent 来获取操作并更新 MapComponent。
编辑添加代码示例:
所以根组件(App)
import React from "react";
import { Provider } from "react-redux";
import Map from "../containers/Map";
import mainStore from "../store";
const store = mainStore();
function AppComponent(props) {
return (
<Provider store={store}>
<Map />
</Provider>
);
}
export default AppComponent;
调用容器 Map 将所有状态数据从 store 传递到组件 MapComponent
import { connect } from "react-redux";
import MapComponent from "../components/MapComponent";
const mapStateToProps = ({ shipR }) => {
return {
shipLocation: [...shipR.shipLocation],
};
};
const mapDispatchToProps = (dispatch) => {
return {
};
};
const Map = connect(mapStateToProps, mapDispatchToProps)(MapComponent);
export default Map;
地图组件:
import React from "react";
import { Provider } from "react-redux";
import mainStore from "../store";
import Ship from "../containers/Ship";
const store = mainStore();
function MapComponent(props) {
return (
<div id="__Map__">
{
<Provider store={store}>
<Ship />
</Provider>
}
</div>
);
}
export default MapComponent;
这个 MapComponent 调用了 ShipComponent 容器
import { connect } from "react-redux";
import ShipComponent from "../components/ShipComponent";
import { generateDefaultShips, shipToggle } from "../actions/shipAction";
const mapStateToProps = ({ shipR }) => {
return {
shipLocation: [...shipR.shipLocation],
};
};
const mapDispatchToProps = (dispatch) => {
return {
genShips() {
dispatch(generateDefaultShips());
},
};
};
const Ship = connect(mapStateToProps, mapDispatchToProps)(ShipComponent);
export default Ship;
ShipComponent 组件如下所示:
import React, { useEffect } from "react";
function ShipComponent(props) {
useEffect(() => {
props.genShips();
}, []);
return (
<div className="ship"></div>
);
}
export default ShipComponent;
genShips() 是一个动作:
import { SHIP_GENERATION_RESULT } from "../constants";
export function generateDefaultShips() {
let arr = [];
for (let x = 0; x < 7; x++) {
arr[x] = [];
for (let y = 0; y < 11; y++) arr[x][y] = null;
}
return { type: SHIP_GENERATION_RESULT, ships: arr };
}
MapComponent 减速器:
const initiateState = {
};
function mapReducer(state = initiateState, action) {
return state;
}
export default mapReducer;
和 ShipComponent 减速器:
import {
SHIP_GENERATION_RESULT,
} from "../constants";
const initiateState = {
shipLocation: [],
};
function shipReducer(state = initiateState, action) {
switch (action.type) {
case SHIP_GENERATION_RESULT: {
return {
...state,
shipLocation: action.ships,
};
}
default:
return state;
}
}
export default shipReducer;
和常量 index.js 包含:
export const SHIP_GENERATION_RESULT = "SHIP_GENERATION_RESULT";
所有这些容器、常量、组件和操作都在不同的文件中
附言子组件 ShipComponent 可以很好地获取 shipLocation 多数组数据,但由于 MapComponent(父级)不会重新渲染,所以他不会。
O 和 reduxers index.js:
import { combineReducers } from "redux";
import mapReducer from "./mapReducer";
import shipReducer from "./shipReducer";
const allReducers = combineReducers({
mapR: mapReducer,
shipR: shipReducer,
});
export default allReducers;
存储 index.js:
import { createStore, applyMiddleware } from "redux";
import thunkMiddleware from "redux-thunk";
import allReducers from "../reducers";
import { composeWithDevTools } from "redux-devtools-extension";
export default function mainStore(prevState) {
return createStore(
allReducers,
prevState,
composeWithDevTools(applyMiddleware(thunkMiddleware))
);
}
【问题讨论】:
-
您能否为
genShips()提供reducer 或最小的可重现示例? -
是的。 imma 删除所有不需要的代码,留下一个最简单的例子。我会尽快更新它
-
@dongnhan 添加了所有组件、reducer 和操作代码,同时删除了此示例不需要的代码。经过测试 - 使用此最低代码仍然会出现同样的问题
-
您正在为 App 和 Map 组件使用不同的商店,应该帮助删除商店及其在 MapComponent 中的提供者。
-
@tuan.tran OMG 谢谢!我很难我需要为使用商店的每个组件重复
。如果您想将答案发布为“答案”而不是评论,那么我可以将其标记为“答案”,这将是非常棒的,这样其他犯过同样错误的人就会有一个快速的答案。再次感谢! :)