示例代码:
const menu = [
{type: "home", visSelector: someSelector},
{type: "accounts", visSelector: anotherSelector}
]
const filterMenuItems = (state, menu) =>
menu.filter(i => i.visSelector(state))
const mapStateToProps = state => {
menuItems: filterMenuItems(state, menu)
}
什么是正确的方式来记住filterMenuItem?
visSelector已经被记住。不幸的是,每次都需要重新呈现过滤结果。
答案 0 :(得分:1)
提供的项目是纯组件,不会全部每次都重新渲染。只是您先前删除过之后要添加的内容。
例如,这里我们以显示的所有四个孩子开始。如果取消选中其中一个复选框,则两个子项会消失,但不会重新渲染任何子项。只有重新添加它们,它们才会重新渲染。
const Child = props => {
console.log("render", props.name);
return <div>{props.name}</div>
}
class Example extends React.Component {
constructor(...args) {
super(...args);
this.children = [
<Child key={0} name="zero" />,
<Child key={1} name="one" />,
<Child key={2} name="two" />,
<Child key={3} name="three" />
];
this.state = {
showOdds: true,
showEvens: true
};
}
evensClick = event => {
this.setState({showEvens: event.currentTarget.checked});
};
oddsClick = event => {
this.setState({showOdds: event.currentTarget.checked});
};
render() {
const {showEvens, showOdds, counter} = this.state;
return <div>
<label>
<input type="checkbox" onChange={this.evensClick} checked={showEvens} />
Show evens
</label>
<label>
<input type="checkbox" onChange={this.oddsClick} checked={showOdds} />
Show odds
</label>
<div>
{this.children.filter((child, index) => index % 2 == 0 ? showEvens : showOdds)}
</div>
</div>;
}
}
ReactDOM.render(
<Example />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
我认为没有办法防止在重新添加它们时重新渲染它们。
或者,您可以使用CSS来管理其可见性,这将阻止重新渲染它们:
const Child = props => {
console.log("render", props.name);
return <div className={props.index % 2 == 0 ? "even" : "odd"}>{props.name}</div>
}
class Example extends React.Component {
constructor(...args) {
super(...args);
this.children = [
<Child index={0} key={0} name="zero" />,
<Child index={1} key={1} name="one" />,
<Child index={2} key={2} name="two" />,
<Child index={3} key={3} name="three" />
];
this.state = {
showOdds: true,
showEvens: true
};
}
evensClick = event => {
this.setState({showEvens: event.currentTarget.checked});
};
oddsClick = event => {
this.setState({showOdds: event.currentTarget.checked});
};
render() {
const {showEvens, showOdds, counter} = this.state;
const cls = (showEvens ? "" : "hide-evens ") + (showOdds ? "" : "hide-odds");
return <div>
<label>
<input type="checkbox" onChange={this.evensClick} checked={showEvens} />
Show evens
</label>
<label>
<input type="checkbox" onChange={this.oddsClick} checked={showOdds} />
Show odds
</label>
<div className={cls}>
{this.children}
</div>
</div>;
}
}
ReactDOM.render(
<Example />,
document.getElementById("root")
);
.hide-evens .even {
display: none;
}
.hide-odds .odd {
display: none;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
答案 1 :(得分:0)
Array.filter()在每次调用时返回一个新数组。您可能想要根据您的应用程序要求来记住filterMenuItems
。
在filterMenuItems
下面的示例中,仅当state
或menu
参数更改时才返回新数组:
import { createSelector } from 'reselect';
const filterMenuItems = createSelector(
state => state,
(state, menu) => menu,
(state, menu) => menu.filter(i => i.visSelector(state))
);