2016-12-29 30 views
0

この質問は、このフォローアップであるリアクト:ネストされたマッチのルートはルータV4とMatchWithFade

Trouble with React Router v4 and MatchWithFade

私はルータV4をMatchWithFadeを使用して反応について別の(潜在的に愚かな)疑問を持っています。私は何をしたいのは、ネストされたルートを持っているので、トップレベルのコンポーネントは、これを持っているかもしれません:

<MatchWithFade pattern='/one' component={One} />

...そしてOneは、この可能性があります:

<Match pattern='/one/one' Component={OneOne} />

をこれは私を珍しいパターン(私はそれかもしれないが)として打つことはありません。いずれにしても、上記の例を使用して、OneOneをロードすると、マウントされ、次にcomponentWillUnmountが直ちに呼び出されます。私が推測するには、TransitionMotionOneOneの(おそらく隠された)インスタンスを追跡しており、移行が完了すると、その隠れたコンポーネントがアンマウントされると言いたいと思います。基本的なUIに関する限り、OneOneがレンダリングされます。しかし、componentWillUnmountが(例えば、Reduxから何かを削除しているような)クリーンアップを行った場合、もちろんそのアクションは起動され、OneOneに関連付けられたデータは吹き飛ばされます。あなたはこれをロードして、コンソール、OneTwoリンク間のトグルを開く

import React, { Component } from 'react'; 
import BrowserRouter from 'react-router/BrowserRouter' 

import { TransitionMotion, spring } from 'react-motion' 
import Match from 'react-router/Match' 
import Link from 'react-router/Link'; 

const styles = { 
    fill: { position: 'absolute', top: 0, left: 0 } 
}; 

const MatchWithFade = ({ component:Component, ...rest }) => { 
    const willLeave =() => ({ zIndex: 1, opacity: spring(0) }) 

    return (
    <Match {...rest} children={({ matched, ...props }) => { 
     return (
     <TransitionMotion 
      willLeave={willLeave} 
      styles={matched ? [ { 
      key: props.location.pathname, 
      style: { opacity: 1 }, 
      data: props 
      } ] : []} 
     > 
      {interpolatedStyles => { 
      return (
       <div> 
       {interpolatedStyles.map(config => (
        <div 
        key={config.key} 
        style={{...styles.fill, ...config.style }}> 
        <Component {...config.data}/> 
        </div> 
       ))} 
       </div> 
      ) 
      }} 
     </TransitionMotion> 
    ) 
    }}/> 
) 
} 

const TwoOne =() => { 
    return (
    <div>Two One</div> 
) 
} 


class TwoTwo extends Component { 
    componentWillUnmount() { 
    console.log("TwoTwo will unmount") 
    } 

    render() { 
    return (
     <div>Two Two</div> 
    ) 
    } 
} 


const TwoHome =() => { 
    return (
    <div>Two Home</div> 
) 
} 


class One extends Component { 
    componentWillUnmount() { 
    console.log("ONE UNMOUNTING") 
    } 
    render() { 
    return (
     <div style={{ width: 300, border: '1px solid black', backgroundColor: 'orange', minHeight: 200}}> 
     One one one one one one one one one one<br /> 
     One one one one one one one one one one<br /> 
     </div> 
    ) 
    } 
} 

const Two =() => { 
    return (
    <div style={{ width: 300, border: '1px solid black', backgroundColor: 'yellow', minHeight: 200}}> 
     <Match pattern='/two/one' component={TwoOne} /> 
     <Match pattern='/two/two' component={TwoTwo} /> 
     <Match pattern='/two(/)?' exactly={true} component={TwoHome} /> 
    </div> 
) 
} 


class App extends Component { 

    render() { 
    return (
     <BrowserRouter> 
      <div style={{padding: 12}}> 
      <div style={{marginBottom: 12}}> 
       <Link to='/one'>One</Link> || <Link to='/two'>Two</Link> 
       || <Link to='/two/one'>Two One</Link> 
       || <Link to='/two/two'>Two Two</Link> 
      </div> 
      <div style={{position: 'relative'}}> 
       <MatchWithFade pattern='/one' component={One} /> 
       <MatchWithFade pattern='/two' component={Two} /> 
      </div> 
      </div> 
     </BrowserRouter> 
    ) 
    } 
} 

export default App; 

場合:

は、ここでの問題を示している完全な例です。 UIでクロスフェードが起こるのを見ると、1から2への移行が完了すると、コンソールに「ONE UNMOUNTING」と表示されます。そうです。

Two OneTwo Twoの間をクリックします。この場合、Two Oneをクリックすると、すぐにコンソールに「TwoTwo unmount」と表示されます。しかし、Two Twoをクリックすると、約2秒後に「TwoTwo unmount」と表示されます。これは、親のMatchWithFadeが実行にかかる時間です。

ここで何が起こっているのか分かりません。私のコードはちょうど破壊されたのですか? RRv4でサポートできないことをやっていますか?私はバグを発見しましたか?

ヘルプ/ガイダンスがありがとうございます。

答えて

1

あなたの問題はprops.location.pathnameをキーとして使用していることです。これは常にコンポーネントと同じにする必要がありますが、記述した方法はナビゲートするたびに変更されます。

const styles = { 
    fill: { position: 'absolute', top: 0, left: 0 } 
}; 

へ:これを変更してみてください

const styles = { 
    fill: { position: 'relative', top: 0, left: 0 } 
}; 

とあなたが(各キーのために1)<Two>の2つのインスタンスをレンダリングしていることがわかります。あなたが一定のkey、などrest.pattern(この<Match>に関連付けられているパターン)を使用した場合

、あなたの問題が離れて行くだろう。

styles={matched ? [ { 
    key: rest.pattern, 
    style: { opacity: 1 }, 
    data: props 
} ] : []} 
+0

Ah!面白い! 'MatchWithFade'コードは、React-Routerのドキュメントからそのまま受け継がれていました。そして、私は 'props.location.pathname'と' rest.pattern'の違いを見ています。 'rest.pattern'は現在の' Match'コンポーネントにマッチするパスの一部で、 'props.location.pathname'は完全パスです。これはyesを意味し、キーは変更され、複数のインスタンスがロードされます。これはおそらく、RRドキュメントが 'props.location.pathname'ではなく' rest.pattern'を使うように更新されなければならないことを意味し、他のものはこの問題に遭遇しません。 – hairbo

+0

これはちょっと複雑に思えるかもしれませんが、私が考えているのはこれです:1)各はユニークです。 2つのアニメーションがある場合、それは2つの異なるアニメーションです。 2)要素は、内の各キーに対して作成されます。 docsの例では、新しい場所の ''がレンダリングされるので、 'props.location.pathname'を使うとキーとしてうまく動作します。あなたのコードでは、ただ一つの ''がレンダリングされるので、変更されないキーが必要です。 –

+0

そうです、それは理にかなっています。そして、そうですね、私の頭の中で私の頭を掴むのは少し難しいですが、浸透し始めています。その例では、 'rest.pattern'はprops.location.pathnameと同じようにキーとして機能します。 'そうですか?そして、誰か(ああ、私のような)がそのコードをスワイプして修正し、そのキーを変更する心配がないという点で、もう少しばかげてしまうという追加の利点があります。 – hairbo

関連する問題