重新选择选择器保持使用相同的输入进行重新计算

时间:2019-10-22 13:25:43

标签: reactjs redux reselect

我不明白为什么重新选择库会使用相同的输入重新计算选择器。我检查了FAQ,但没有回答我的问题。

这是一个有关react,redux,重新选择的示例

Codesandbox

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";
import { createSelector } from "reselect";

const initialState = {
  counter: 1
};

const reducer = (state = initialState, action) => {
  if (action.type === "INCREMENT") {
    return { ...state, counter: state.counter + 1 };
  }
  if (action.type === "DECREMENT") {
    return { ...state, counter: state.counter - 1 };
  }
  return state;
};

const store = createStore(reducer);

class ChildComp extends React.Component {
  handleIncrement = () => {
    this.props.increment();
  };

  handleDecrement = () => {
    this.props.decrement();
  };

  render() {
    const { counter, isEven } = this.props;
    return (
      <div>
        <div>counter: {counter}</div>
        <div>is even: {JSON.stringify(isEven)}</div>
        <button onClick={this.handleIncrement}>increment</button>
        <button onClick={this.handleDecrement}>decrement</button>
      </div>
    );
  }
}

const getCounter = state => state.counter;
const isEvenSelector = createSelector(
  getCounter,
  counter => {
    console.log("calculate is even for", counter);
    return counter % 2 === 0;
  }
);

const mapStateToProps = state => {
  return {
    counter: state.counter,
    isEven: isEvenSelector(state)
  };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: "INCREMENT" }),
    decrement: () => dispatch({ type: "DECREMENT" })
  };
};

const Child = connect(
  mapStateToProps,
  mapDispatchToProps
)(ChildComp);

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Child />
      </Provider>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

预期行为:

初始值(计数器1)//计算为1的偶数
增量(计数器2)//计算2为偶数
减量(计数器1)//不应该console.log,因为已经计算出结果

实际行为:

初始值(计数器1)//计算为1的偶数
增量(计数器2)//计算2为偶数
减量(计数器1)//计算为1的偶数

1 个答案:

答案 0 :(得分:2)

仅缓存上一组输入的结果。

The docs say:

  

使用createSelector创建的选择器的缓存大小为1。这意味着当输入选择器的值更改时,它们始终会重新计算,因为选择器仅存储每个输入选择器的前一个值。

因此,如果counter的值未更改,则不会看到任何控制台日志。但由于与上次执行选择器函数的时间不同,因此必须再次计算结果。