当状态对象重新排序时,React组件重新安装

时间:2019-07-03 16:46:09

标签: reactjs redux react-redux

我有一个react-redux应用程序,当子组件位置在状态更改中发生变化时,我正在使用react-transition-group进行转换。但是,如果我的redux状态对象的顺序改变了,组件将被卸载然后重新安装,而不是更新。这样可以防止组件平稳过渡到新位置。有没有解决此问题的方法而又不引入新状态?

我的父组件如下所示:

class ParentComponent extends Component {
...
render() {
return (
   <div>
      <div>
         <CSSTransitionGroup>
            <ChildComponents childComponentsToRender= 
               {this.props.someChildComponents}/>
         <CSSTransitionGroup/>
      </div>
   </div>
)}}

ChildComponents看起来像这样:

export default function ChildComponents(props) {
   const childrenToReturn = _.map(props.childComponentsToRender, 
      (childComponent) => 
      <ChildComponent 
         key={childComponent.uniqueId} 
         position={childComponent.position} .../>
   return (
      <Fragment>
         {childrenToReturn}
      </Fragment>
   )
}

一个单独的ChildComponent看起来像这样:

export default function ChildComponent(props) {
   return (
      <div style={{transform: `translate(${props.position.x}px, 
         ${props.position.y}px)`}}>
      </div>
   )
}

我呈现组件的redux状态如下:

{
   ...,
   someChildComponents: {
      childComponent1: {
         id: someUniqueId,
         position: {x: int, y: int}
      },
      childComponent2: {
         id: someUniqueId,
         position: {x: int, y: int}
      },
      ...
   },
   ...
}

例如,如果调度了某个动作并且状态从以下更改,则会发生此问题:

{
   someChildComponents: {
      childComponent1: {
         id: someUniqueId,
         position: {x: 100, y: 100}
      },
      childComponent2: {
         id: someUniqueId,
         position: {x: 200, y: 200}
      }
   }
}

收件人:

{
   someChildComponents: {
      childComponent2: {
         id: someUniqueId,
         position: {x: 300, y: 300}
      },
      childComponent1: {
         id: someUniqueId,
         position: {x: 150, y: 150}
      }
   }
}

1 个答案:

答案 0 :(得分:0)

如果需要关联元素的特定位置,则最好需要数组而不是对象。但是我不建议将someChildComponents转换为数组。在大多数情况下,存储不同的数据时,对象优先于数组。

您可以基于someChildComponents对象动态创建数组,例如使用selectors。您唯一需要的是someChildComponents对象中的一些唯一标识符,该标识符可用于对数组进行排序。

这是示例代码

const getChildrenComponents = state => state.someChildComponents;

export function makeArrayFromChildrenComponents() {
    return createSelector(
        [getChildrenComponents],
        (ChildrenComponents) => (
            Object.keys(ChildrenComponents).map(key => ChildrenComponents[key])
                .sort((e1, e2) => {
                    if (e1.id === e2.id) return 0;
                    return e1.id < e2.id ? -1 : 1;
                });
        )
    )
}

然后使用它为ParentComponent这样的子组件提供稳定的数组

const makeMapStateToProps = () => {
    const getChildrenComponentsArray = makeArrayFromChildrenComponents();
    const mapStateToProps = (state) => ({
        ChildrenComponents: getChildrenComponentsArray(state)
        // ... other mapped props
    });
    return mapStateToProps;
}

选择器将在状态更改时更新ChildrenComponents。但是数组本身将拥有相同顺序的元素。

您还可以查看React用来决定是构建新树还是保留现有树的diffing algorithm