我正在使用 redux 将菜单数据存储在商店中。
它工作正常,但是一旦我通过调度更新商店,组件就不会重新渲染,如果我使用this.forceUpadate
它可以工作,但我不想使用它。有没有解决方案。
法典
class MenuContents extends Component {
constructor() {
super();
this.state = {
menu : []
}
}
componentDidMount() {
// populate the left menu
fetch("./services/left-menu.json")
.then(res => res.json())
.then(data => {
store.dispatch( addLeftMenu(data))
this.forceUpdate(); // I dont want to use this
}).catch(function() {
console.log("An error occured during fetch operation.");
});
}
render() {
let storeValue = store.getState();
const leftMenu = storeValue.leftMenu[0];
const isMenuLoaded = leftMenu !== undefined && leftMenu !== "";
let menuContents;
let menu;
if(isMenuLoaded) {
menuContents = leftMenu.map((menuItem, index)=> {
menu = <li role="presentation" key={index}>
<a className="accordion-toggle" data-toggle="accordion" href="#">
{menuItem.name}
</a>
</li>;
return menu;
}
);
menuContents = <ul className="nav nav-pills nav-stacked"> {menuContents} </ul>;
}
else {
menuContents = <Spinner />
}
return (<div>{menuContents}</div>);
}
}
export default MenuContents;
请参阅下面的减速器代码。
减速器/索引器.js
import { ADD_LEFT_MENU } from "../constants/action-types";
const initialState = {
leftMenu: []
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_LEFT_MENU:
return { ...state, leftMenu: [...state.leftMenu, action.payload]};
default:
return state;
}
};
export default rootReducer;
我认为脱离Sakhi Mansoor所说的,你想将你的组件连接到redux存储。这是一篇文章,我认为它很好地解释了它:
https://medium.com/mofed/reduxs-mysterious-connect-function-526efe1122e4
基本上,当反应组件的状态或道具发生变化时,它们会重新渲染。现在你有一个组件,你有一个商店。需要发生的是,您将触发一些操作,这些操作将返回要由化简器消耗的东西。化简器将更新 redux 存储。然后理想情况下,商店将更新组件的道具,然后触发重新渲染。
我认为你缺少的是最后一部分。当您像文章中那样调用连接时,它会将存储连接到组件。因此,每当商店的某些部分发生变化时,它都会更新组件中的关联道具。
如果你的 fetch 调用没有导致组件的 props 或状态发生变化,React 就无法知道你的组件需要重新渲染。你应该用 react-redux 连接你的组件。直接在组件中访问 redux 存储不是通常的做法,不建议这样做。大多数生态系统都是围绕连接的组件构建的。
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
class MenuContents extends Component {
constructor() {
super();
this.state = {
menu : []
}
}
componentDidMount() {
// populate the left menu
fetch("./services/left-menu.json")
.then(res => res.json())
.then(data => {
store.dispatch( addLeftMenu(data))
}).catch(function() {
console.log("An error occured during fetch operation.");
});
}
render() {
let storeValue = store.getState();
const leftMenu = storeValue.leftMenu[0];
const isMenuLoaded = leftMenu !== undefined && leftMenu !== "";
let menuContents;
let menu;
if(isMenuLoaded) {
menuContents = leftMenu.map((menuItem, index)=> {
menu = <li role="presentation" key={index}>
<a className="accordion-toggle" data-toggle="accordion" href="#">
{menuItem.name}
</a>
</li>;
return menu;
}
);
menuContents = <ul className="nav nav-pills nav-stacked"> {menuContents} </ul>;
}
else {
menuContents = <Spinner />
}
return (<div>{menuContents}</div>);
}
}
const mapStateToProps = state => ({
leftMenu: state.leftMenu,
});
const mapDispatchToProps = dispatch => ({
addLeftMenu: bindActionCreators(addLeftMenu, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(MenuContents);