Реагировать компонент перемонтируется при изменении состояния объекта - PullRequest
0 голосов
/ 03 июля 2019

У меня есть приложение response-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>
   )
}

Мое избыточное состояние, которое отображает компоненты, выглядит следующим образом:

{
   ...,
   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 голосов
/ 04 июля 2019

Если вам нужно определить конкретную позицию элемента, вам лучше использовать массив, а не объект. Но я не рекомендую конвертировать someChildComponents в массив. В большинстве случаев объект предпочтительнее массива при хранении различных данных.

Вы можете создать массив на лету на основе вашего someChildComponents объекта, например, используя селекторы . Единственное, что вам нужно, это какой-то уникальный идентификатор внутри 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, чтобы решить, строить ли новое дерево или сохранять существующее.

...