如何记住选择器数组?

时间:2018-06-26 15:05:28

标签: javascript reactjs reselect

示例代码:

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已经被记住。不幸的是,每次都需要重新呈现过滤结果。

2 个答案:

答案 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下面的示例中,仅当statemenu参数更改时才返回新数组:

import { createSelector } from 'reselect';

const filterMenuItems = createSelector(
    state => state,
    (state, menu) => menu,
    (state, menu) => menu.filter(i => i.visSelector(state))
);