React TransitionGroup and React.cloneElement do not send updated props

前端 未结 1 1125
情话喂你
情话喂你 2021-02-05 14:46

I am following Chang Wang\'s tutorial for making reusable React transitions with HOCs and ReactTransitionGroup(Part 1 Part 2) in conjunction with Huan Ji\'s tutoria

相关标签:
1条回答
  • 2021-02-05 14:54

    Determining Entering and Leaving Children

    Imagine rendering the sample JSX below:

    <TransitionGroup>
      <div key="one">Foo</div>
      <div key="two">Bar</div>
    </TransitionGroup>
    

    The <TransitionGroup>'s children prop would be made up of the elements:

    [
      { type: 'div', props: { key: 'one', children: 'Foo' }},
      { type: 'div', props: { key: 'two', children: 'Bar' }}
    ]
    

    The above elements will be stored as state.children. Then, we update the <TransitionGroup> to:

    <TransitionGroup>
      <div key="two">Bar</div>
      <div key="three">Baz</div>
    </TransitionGroup>
    

    When componentWillReceiveProps is called, its nextProps.children will be:

    [
      { type: 'div', props: { key: 'two', children: 'Bar' }},
      { type: 'div', props: { key: 'three', children: 'Baz' }}
    ]
    

    Comparing state.children and nextProps.children, we can determine that:

    1. { type: 'div', props: { key: 'one', children: 'Foo' }} is leaving

    2. { type: 'div', props: { key: 'three', children: 'Baz' }} is entering.

    In a regular React application, this means that <div>Foo</div> would no longer be rendered, but that is not the case for the children of a <TransitionGroup>.

    How <TransitionGroup> Works

    So how exactly is <TransitionGroup> able to continue rendering components that no longer exist in props.children?

    What <TransitionGroup> does is that it maintains a children array in its state. Whenever the <TransitionGroup> receives new props, this array is updated by merging the current state.children and the nextProps.children. (The initial array is created in the constructor using the initial children prop).

    Now, when the <TransitionGroup> renders, it renders every child in the state.children array. After it has rendered, it calls performEnter and performLeave on any entering or leaving children. This in turn will perform the transitioning methods of the components.

    After a leaving component's componentWillLeave method (if it has one) has finished executing, it will remove itself from the state.children array so that it no longer renders (assuming it didn't re-enter while it was leaving).

    Passing Props to Leaving Children?

    Now the question is, why aren't updated props being passed to the leaving element? Well, how would it receive props? Props are passed from a parent component to a child component. If you look at the example JSX above, you can see that the leaving element is in a detached state. It has no parent and it is only rendered because the <TransitionGroup> is storing it in its state.

    When you are attempting to inject the state to the children of your <TransitionGroup> through React.cloneElement, the leaving component is not one of those children.

    The Good News

    You can pass a childFactory prop to your <TransitionGroup>. The default childFactory just returns the child, but you can take a look at the <CSSTransitionGroup> for a more advanced child factory.

    You can inject the correct props into the children (even the leaving ones) through this child wrapper.

    function childFactory(child) {
      return React.cloneElement(child, {
        transitionState,
        dispatch
      })
    }
    

    Usage:

    var ConnectedTransitionGroup = connect(
      store => ({
       transitionState: state.transitions
      }),
      dispatch => ({ dispatch })
    )(TransitionGroup)
    
    render() {
      return (
        <ConnectedTransitionGroup childFactory={childFactory}>
          {children}
        </ConnectedTransitionGroup>
      )
    }
    

    React Transition Group was somewhat recently split out of the main React repo and you can view its source code here. It is pretty straightforward to read through.

    0 讨论(0)
提交回复
热议问题