Reactjs 当多个组件为其使用复杂对象的部分时,redux如何工作';s源

Reactjs 当多个组件为其使用复杂对象的部分时,redux如何工作';s源,reactjs,react-native,redux,react-redux,Reactjs,React Native,Redux,React Redux,我有一个对象(这是一个属性数组,因为它是动态的,所以我不能将它拆分为多个属性),我将其保存在reducer中,看起来像这样: [ {type: list, elements: []} {type: map, elements: []} {type: wheelList, elements: []} {type: chart, elements: []} {type: dyna, elements: []} ... ] { isFetching: false, d

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

[
  {type: list, elements: []}
  {type: map, elements: []}
  {type: wheelList, elements: []}
  {type: chart, elements: []}
  {type: dyna, elements: []}
  ...
]
{
  isFetching: false,
  didInvalidate: false,
  data: [
    { type: 'list', id: 1, name: 'test' },
    { type: 'list', id: 2, name: 'test1' },
    { type: 'map', id: 3, name: 'test' },
    { type: 'map', id: 4, name: 'test1' },
    { type: 'list', id: 5, name: 'test' },
    { type: 'list', id: 6, name: 'test1' },
    { type: 'list', id: 7, name: 'test' },
    { type: 'list', id: 8, name: 'test1' },
  ]
}
在一个组件中,我从存储中获取并访问它,如下所示:

this.props.allElements
然后,我为每个组件呈现不同的组件(伪代码):

减速器:

export default function (state:State = initialState, action:Action): State {
  if (action.type === 'ELEMENTS_RECEIVED') {
    return {
      ...state,
      allElements: action.allElements,
    };
在大组件中:

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
    )
}

数据示例:

[
  {
    "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"
      }
    ]
  }
]

您可以在
thunk
操作
中执行循环,并将数据拆分为单独的
缩减器

您的操作可以如下所示:

// 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
          });

        // ....
      }
    });
  }
}
// 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,
    }
  }
}
// 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>
  );
}
您的单独减速机可能看起来像这样:

// 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
          });

        // ....
      }
    });
  }
}
// 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,
    }
  }
}
// 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>
  );
}
然后您可以这样渲染它:

// 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
          });

        // ....
      }
    });
  }
}
// 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,
    }
  }
}
// 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>
  );
}
//在组件渲染方法中
render(){
const{list,map}=this.props;//redux数据作为props从单独的还原器传递
返回(
);
}
编辑
作为您评论的后续内容:

如果我将allData放入父对象,并将allData.xyz传递给渲染中的组件 当任何数据更改时,父级也将按其道具的状态重新播放 改变

嗯,重新呈现父对象并没有什么错。当
组件的
render
方法运行时,并不意味着它将重新渲染到物理
DOM
,它将更新或覆盖虚拟
DOM
的对象,然后通过检查物理
DOM
与虚拟
DOM
之间的差异,以确定何时,物理的
DOM
应该如何以及在哪里更新。
它只能更新
DOM
元素的某些属性,而无需重新渲染它们


您还可以选择,但我强烈建议您不要这样做。

在您的数据示例中,有多个项目具有相同的类型(例如:列表)

Redux不建议使用这种嵌套对象,因为您将无法优化渲染,也无法优化数据失效

优化的一种方法是将数据展平,使其看起来像这样:

[
  {type: list, elements: []}
  {type: map, elements: []}
  {type: wheelList, elements: []}
  {type: chart, elements: []}
  {type: dyna, elements: []}
  ...
]
{
  isFetching: false,
  didInvalidate: false,
  data: [
    { type: 'list', id: 1, name: 'test' },
    { type: 'list', id: 2, name: 'test1' },
    { type: 'map', id: 3, name: 'test' },
    { type: 'map', id: 4, name: 'test1' },
    { type: 'list', id: 5, name: 'test' },
    { type: 'list', id: 6, name: 'test1' },
    { type: 'list', id: 7, name: 'test' },
    { type: 'list', id: 8, name: 'test1' },
  ]
}
app.js

class App extends React.Component {
  render() {
    return (
      <div>
        <ListComponent />
        <MapComponent />
      </div>
    );
  }
}
ListComponent.js

class App extends React.Component {
  render() {
    return (
      <div>
        <ListComponent />
        <MapComponent />
      </div>
    );
  }
}
这里的技巧是只传递元素
id
,并让子元素检查何时重新加载

请注意,
ListComponent
仅当
listElements
值中有任何修改时才会重新加载。 示例:

  • 现在有一个“列表”类型的新项
  • 有一个“列表”类型的已删除项
  • 已修改当前“列表”项目之一
代码:

请记住,API可能会以某种方式向您发送格式化的数据,但您可以根据需要重新格式化它们

一篇关于此类优化的有趣文章:

如果您想在redux中进一步使用数据规范化最佳实践:


希望有帮助。

那你为什么不把它分成不同的减速机呢?我真的能从中受益吗?这是我从服务器获取的对象,它是非常动态的。这就是为什么我要求解释react将如何处理这种情况。我认为在
渲染
中执行此操作不如在
thunk
(action creator)中执行此循环,并将每个
类型
分配到不同的
减速机
。您能给我一些指导或示例,在我的情况下如何执行此操作?我真的不明白如何分割它。现在我循环遍历所有元素,从中提取元素并进行渲染。现在一切都在一个属性中。正如我所说的,只有map经常更新,因为它会重新渲染。好的,发布您的操作和还原程序,以这种方式获取并传递
this.props.allegements
。如果地图更新列表将不会重新渲染和相反。是的,不会重新渲染,如果没有新的道具或状态改变内部我明白了。但我会等着接受答案。如果我得到3个列表和3个地图作为响应,这个解决方案就帮不了我。每个AN都需要不同的减速器。或者我错了,这可以应用到这个问题上。这和你现在在这个方面所做的没有什么不同。我只是将组件外部的逻辑移到了redux流。如果每个对象都是一个数组,那么reducer的数据结构就是一个数组,你也可以映射到它上面。对不起,你能更新一下答案吗?如果我看到它,我会更好地理解它。假设你有3个列表和一张地图。顺便说一句,感谢您的帮助:-)