当多个组件使用复杂对象的一部分作为源时,redux如何工作

111*_*110 10 reactjs react-native redux react-redux

我有一个对象(这是一个属性数组,因为它是动态的,我不能将它拆分为多个属性),我保留在reducer中看起来像这样:

[
  {type: list, elements: []}
  {type: map, elements: []}
  {type: wheelList, elements: []}
  {type: chart, elements: []}
  {type: dyna, elements: []}
  ...
]
Run Code Online (Sandbox Code Playgroud)

在一个组件中,我从商店获取它并访问它,如:

this.props.allElements
Run Code Online (Sandbox Code Playgroud)

然后对于每一个我渲染不同的组件(伪代码):

foreach (el in this.props.allElements) {
   if (el == list) {
      return <ListComponent elements={el.elements}>
   }
   if (el == map) {
      return <MapComponent elements={el.elements}>
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

这样每个组件只获得感兴趣的元素.
我的问题是关于性能和优化.

我的方法有什么好处吗?

我遇到了一些性能问题,所以检查我的组织
是否有错,如果可以改进则需要建议.
我有一些频繁的更新,有时候地图可以每秒更新一次.

因此,如果我仅更新地图元素并将其传递给操作以进行更新,则所有这些组件将再次运行渲染或仅运行观察地图.


UPDATE

但是更新map我需要得到全本内容object来自storeaction update only map元素,然后整个更新的对象传递给reducer.
所以只有地图被改变,其他人则没有.
react/redux足够智能,只更新数据更改的组件(在我的情况下映射).
行动:

export function getScreenElements() : Action {
  return function(dispatch) {
    // get data from server here
    // and do some calculations here
    dispatch({
                type: 'ELEMENTS_RECEIVED',
                allElements: data
            });
Run Code Online (Sandbox Code Playgroud)

减速器:

export default function (state:State = initialState, action:Action): State {
  if (action.type === 'ELEMENTS_RECEIVED') {
    return {
      ...state,
      allElements: action.allElements,
    };
Run Code Online (Sandbox Code Playgroud)

在大组件中:

const mapStateToProps = state => ({
  allElements: state.main.allElements
...
class Main extends Component {
...
componentDidMount() {
    // here I actually make a call to get data
}
...
render() {
    return (
       // Here is the big code
       // Loop over props.allElements
       // and render it in different way based on data inside each element
    )
}
Run Code Online (Sandbox Code Playgroud)


数据示例:

[
  {
    "type": "list",
    "count": 99,
    "elements": [
      {
        "id": 1,
        "name": "test"
      },
      {
        "id": 2,
        "name": "test1"
      }
    ]
  },
  {
    "type": "map",
    "count": 99,
    "elements": [
      {
        "id": 3,
        "name": "test"
      },
      {
        "id": 4,
        "name": "test1"
      }
    ]
  },
  {
    "type": "list",
    "count": 99,
    "elements": [
      {
        "id": 5,
        "name": "test"
      },
      {
        "id": 6,
        "name": "test1"
      }
    ]
  },
  {
    "type": "list",
    "count": 99,
    "elements": [
      {
        "id": 7,
        "name": "test"
      },
      {
        "id": 8,
        "name": "test1"
      }
    ]
  }
]
Run Code Online (Sandbox Code Playgroud)

Sag*_*b.g 6

您可以在内部循环thunk action并将数据拆分为单独的reducers.

You Action看起来像这样:

// action thunk
export function getScreenElements() {
  return function (dispatch) {
    // get data from server here
    const dataFromServer = fetch('url');
    // do your looping here and dispatch each data acording to its type
    dataFromServer.map(obj => {
      switch (obj.type) {
        case 'list':
          dispatch({
            type: 'LIST_RECEIVED',
            listElements: obj
          });

        case 'map':
          dispatch({
            type: 'MAP_RECEIVED',
            mapElements: obj
          });

        // ....
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

你的单独减速器看起来像这样:

// map reducer
export default function map(state = initialState, action) {
  if (action.type === 'MAP_RECEIVED') {
    return {
      ...state,
      mapElements: action.mapElements,
    }
  }
}


// list reducer
export default function list(state = initialState, action) {
  if (action.type === 'LIST_RECEIVED') {
    return {
      ...state,
      listElements: action.listElements,
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样呈现它:

// inside your component render mehtod
render(){
  const { list, map } = this.props; // redux data passed as props from the seperate reducers
  return (
    <div>
      <ListComponent elements={list}>
        <MapComponent elements={map}>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑
作为评论的后续内容:

如果我将allData放到parent并将allData.xyz传递给render中的组件,当任何数据更改时,parent也将reRender,因为它的props已被更改

好吧,父母被重新渲染没有错.当运行render方法component并不意味着它将重新渲染到物理时DOM,它将更新或覆盖虚拟对象,DOM然后DOM通过对帐和漫射算法检查物理和虚拟之间的差异,以确定何时,物理如何以及在何处DOM更新.
它只能更新DOM元素的某些属性而无需重新渲染它们,React Only Updates什么是必要的.

还有React.PureComponent的选项,但我强烈反对你的情况.