Javascript 通过容器传递函数以派生状态
我有一个容器,目前的结构如下:Javascript 通过容器传递函数以派生状态,javascript,reactjs,redux,react-redux,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) => (
// 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
}
}
导出默认类ProductGrid扩展React.PureComponent{
静态contextTypes={store:PropTypes.object};
onDrop=()=>{
const state=this.context.store.getState();
//在这里做什么都行
}
}
但理想情况下,我只需要传递一个函数引用,该引用将从我的redux存储中派生状态
是否可以通过
react redux
容器传递派生状态的函数?组件通常无法访问整个存储状态,因为这对性能不利。如果从mapState
函数返回整个存储状态,则组件将在每次调度的操作上重新呈现,而不仅仅是在它真正需要的数据发生更改时
因此,如果您的组件需要访问一个单独的状态来做出其他决策,那么您有两个主要选择:
- 提取该附加信息并将其与组件实际需要渲染的数据一起返回到
mapState
- 将该逻辑移到thunk函数中,该函数可以访问
getState
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);
函数openModalIfSelected(){
返回(调度,获取状态)=>{
const state=getState();
const selected=selecteditems(状态);
如果(选定。长度){
调度(openMoveRequestModal());
}
}
}
//稍后,在组件文件中
const actionCreators={openModalIfSelected};
类ProductGrid扩展组件{
render(){
返回(
{/*此处的所有正常渲染内容*/}
);
}
}
导出默认连接(空,actionCreators)(ProductGrid);
如果您知道在所有情况下,当选择发生更改时,组件不需要重新渲染,那么只要告诉React to skip re re renders(仅当选择发生更改):
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
时,性能是很重要的,因为它在每个可能的渲染时都会被调用(即当道具或状态发生变化时)。请看一看。它正是你所需要的,我不认为它是吗?它通过从state派生的数据并利用memonization,我不认为它给了我派生state的函数。这一节中的一个例子(带有expensiveSelector
)怎么样?