传递函数以通过容器

时间:2018-05-02 14:47:24

标签: javascript reactjs redux react-redux

我有一个目前结构如下的容器:

// container.ts
import { connect } from 'react-redux';
import { selectItems } from './actions';
import { selectSelectedItems } from './selectors';
import component from './component';

const mapStateToProps = (state: AppState) => ({
  selected: selectSelectedItems(state),
});

const mapDispatchToProps = {
  select: selectItems,
}

export default connect(mapStateToProps, mapDispatchToProps)(component);

但是,在这种情况下,只要选择发生更改,组件的每个实例都会更新。

我真正需要的是一个函数,它从redux商店派生状态,出于性能原因可以在某些事件挂钩中调用它。例如,如果选择任何项目,我需要有条件地打开一个模态。它会像这样实现。

onDrop = () => {
  // if there are any selected at all,
  // open a modal for the user.
  const selected = this.props.getSelected();
  if (selected.length) {
    this.openMoveRequestModal();
  }
}

我可以通过一种非常难看的方法让它“起作用”。

export default class ProductGrid extends React.PureComponent<Props> {
  static contextTypes = { store: PropTypes.object };

  onDrop = () => {
    const state = this.context.store.getState();
    // do whatever here
  }
}

理想情况下,我只能通过一个函数引用来从我的redux商店中获取状态。

是否可以通过react-redux容器传递一个导出状态的函数?

2 个答案:

答案 0 :(得分:0)

组件通常无法访问整个商店状态,因为这对性能有害。如果从mapState函数返回整个商店状态,该组件将在每个调度操作上重新呈现,而不仅仅是在它真正需要更改的数据时。

因此,如果您的组件需要访问该州的单独部分以做出其他决策,那么您有两个主要选择:

  • 提取该额外信息并将其与mapState中的组件以及组件实际需要呈现的数据一起返回
  • 将该逻辑移出到thunk函数中,该函数可以访问getState

我建议使用thunk。

示例:

function openModalIfSelected() {
    return (dispatch, getState) => {
        const state = getState();

        const selected = selectSelectedItems(state);

        if(selected.length) {
            dispatch(openMoveRequestModal());
        }
    }
}

// later, in the component file

const actionCreators = {openModalIfSelected};

class ProductGrid extends Component {
    render() {
        return (
            <div>
                {/* all the normal rendering stuff here */}
                <DropTarget onDrop={this.props.openModalIfSelected} />
            </div>
        );
    }
}

export default connect(null, actionCreators)(ProductGrid);

答案 1 :(得分:0)

如果你知道在所有情况下你的组件在选择发生变化时不需要重新渲染,那么只要选择发生了变化,你就可以告诉React跳过重新渲染:

export default class ProductGrid extends React.PureComponent {
  static propTypes = {
    selected: PropTypes.array.isRequired,
    /* others... */
  }

  shouldComponentUpdate (nextProps, nextState) {
    // If any props other than "selected" changed, re-render.
    // Otherwise, if no props or only "selected" changed, skip the render.
    const changedProps = getChangedProps(this.props, nextProps)
    changedProps.delete('selected')
    return changedProps.size > 0
  } 
}

function getChangedProps (currentProps, nextProps) {
  return new Set(
    Object.keys(currentProps)
      .filter(propName => currentProps[propName] !== nextProps[propName])
  )
}

shouldComponentUpdate是一种基于某些条件(道具和州的属性)避免重新渲染的机制。如果函数返回false,则组件将不会呈现,直到它获得新的道具或状态 - 此时将再次调用shouldComponentUpdate

在实施shouldComponentUpdate时,性能非常重要,因为它会在每个可能的渲染上调用(即每当道具或状态发生变化时)。