跨多个comoponents重新选择只能使用deepEqual check

时间:2018-03-15 13:33:14

标签: performance reactjs redux memoization reselect

我已经以各种方式进行过测试......但是,它无法正常工作。 我似乎没有做错什么

  • 与重新选择doc完全相同的代码
  • redux store全部归一化
  • reducers都是不可变的

从父组件中,我只传递一个带有id和来自子组件的prop,与redux连接并使用selector来获取id(来自父组件)的精确项目

### This is what Parent components render looks like
render() {
    return (
      <div>
        <h4>Parent component</h4>
        {this.props.sessionWindow.tabs.map(tabId => 
           <ChildComponentHere key={tabId} tabId={tabId} />  
        )}
      </div>
    );
  }

### This is what Child component looks like
render() {
    const { sessionTab } = this.props  (this props is from connect() )
    <div>
        <Tab key={sessionTab.id} tab={sessionTab} />
      </div>
    ))
  }
### Selectors for across multiple components
const getTheTab = (state: any, ownProps: IOwnProps) => state.sessionWindows.sessionTab[ownProps.tabId];
const makeTheTabSelector = () =>
  createSelector(
    [getTheTab],
    (tab: object) => tab
  )
export const makeMapState = () => {
  const theTabSelector = makeTheTabSelector();
  const mapStateToProps = (state: any, props: IOwnProps) => {
    return {
      sessionTab: theTabSelector(state, props)
    }
  }
  return mapStateToProps
}

奇怪的工作解决方案:只需更改为深度相等检查。(从任何地方)

  • 使用具有深度相等性的选择器按预期工作。
  • at shouldComponentUpdate。使用_.isEqual也有效。

 1. const createDeepEqualSelector = createSelectorCreator(
       defaultMemoize,
       isEqual
    )
 2. if (!_isEqual(this.props, nextProps) || !_isEqual(this.state, nextState)){return true}

根据我的理解,我的redux总是不可变的,所以当有些东西发生变化它会产生新的引用(对象或数组),这就是重新渲染的原因。但是当有100个项目并且只更改了1个项目时,只有具有更改道具的组件才能重新渲染。

为了实现这一点,我只传递id(只是字符串。浅等号(===)正常工作?)使用此id,得到精确项目。(大多数组件得到相同的值输入但很少有组件得到不同有价值的输入)使用重新选择来记忆值。当更新某些内容并且每个组件获得新的引用输入时与memoized值进行比较,并在更改某些内容时重新呈现。

这主要是我现在能想到的......如果我还是要使用_isEqual,为什么要使用重新选择?我很确定我在这里遗漏了一些东西。有人可以帮忙吗?

更多说明。(希望......) 首先,我的redux数据结构就像这样

sessionWindow: {
  byId: {  // window datas byId
    "windowId_111": {
      id: "windowId_111",
      incognito: false,
      tabs: [1,7,3,8,45,468,35,124] // this is for the order of sessionTab datas that this window Item has
    },
    "windowId_222": {
      id: "windowId_222",
        incognito: true,
        tabs: [2, 8, 333, 111]
    },{
      ... keep same data structure as above
    }
  },
  allIds: ["windowId_222", "windowId_111"] // this is for the order of sessionWindow datas
}
sessionTab: {  // I put all tab datas here. each sessionTab doesn't know which sessionWindow they are belong to
  "1": {
    id: 1
    title: "google",
    url: "www.google.com",
    active: false,
    ...more properties
  },
  "7": {
    id: 7
    title: "github",
    url: "www.github.com",
    active: true
  },{
    ...keep same data structure as above
  }
}

问题。 1.当一小部分数据发生变化时,它会重新渲染所有其他组件。   让我们说sessionTab的id为7,网址和标题都改变了。在我的sessionTab Reducer中调度了'SessionTabUpdated'动作。这是减速器逻辑

const updateSessionTab = (state, action) => {
  return {
    ...state,
    [action.tabId]: {
      ...state[action.tabId],
      title: action.payload.title,
      url: action.payload.url
    }
  }
}

没有任何事情被打破。只使用基本重新选择不会阻止重新渲染其他组件。我必须使用深度相等版本来停止重新渲染组件而不更改数据

几天后我一直在努力,我开始认为问题可能来自我的redux数据结构?因为即使我从sessionTab更改了一个项目,它总是会创建新的引用,如{... state,[changedTab'id]:{....}}最后,我不知道...

0 个答案:

没有答案