2017-10-31 13 views
2

React Appをアップグレードする段階にあり、ラップされたコンポーネントをReact Router(V4などのもの)に渡すことに長時間苦労した後、コンポーネントが新しい小道具が渡されるたびに「再マウント」ようになります。ラップされたコンポーネントをReact Routerに渡す方法

ここで包まれたコンポーネント...

export default function preload(WrappedComponent, props) { 
    class Preload extends React.Component { 
     componentWillMount() { 
      getDataForComponent(props); 
     } 

     render() { 
      return <WrappedComponent {...props} />; 
     } 
    } 
    return Preload; 
} 

そして、ここでは、我々はそれを使用している方法ですが...

const FlagsApp = (props) => { 
    return (
     <Route path="/report/:reportId/flag/:id/edit" component{preload(FlagForm, props)} /> 
    ); 
}; 
です

アクションをディスパッチしてからアップデートを受信するたびに、コンポーネントが再マウントされ、多くの問題が発生します。あなたはそれぞれのRoute.componentするための新しい関数を渡す

  • たびに新しいコンポーネントクラスを作成したレンダリング中withRouter(..)を呼び出し

    • :場合はgithubの上this threadによると、コンポーネントが再マウントされますレンダリング、例えば
    • は は、私が直接に FlagFormコンポーネントを渡す場合、問題が固定されているだけでなく、新しいコンポーネントを作成することになる、 {...}} />匿名関数を

    使用して、その後私は利用することができませんpreloadの機能の

    コンポーネントの再インストールを行わずに同じ結果を得るにはどうすればよいですか?

    ありがとうございました!

  • +0

    あなたはプリロードがどのように動作するかを少し説明していただけますか?それは受信非常に最初の小道具で一度だけデータを求めるべきでしょうか?それとも、小道具の変更にも対応すべきでしょうか?プリロードに必要な小道具はどこから来たのですか? –

    答えて

    1

    Routeが新しいアップデートをインストールするのは、毎回preloadで新しいクラスが割り当てられたためです。

    実際、preloadへの各呼び出しは、常に同じ引数で呼び出さ明確な匿名クラス、でも 返します。問題がpreloadが内部と呼ばれているということであるから、だから、

    console.log(preload(FlagForm,props) != preload(FlagForm,props)) // true 
    

    FlagsAppコンポーネントのrenderメソッドの場合は、そのスコープの外に移動して開始します。

    const PreloadedFlagForm = preload(FlagForm, props) //moved out 
    
    const FlagsApp = (props) => { 
        return (
         <Route path="/report/:reportId/flag/:id/edit" 
          component={PreloadedFlagForm} /> //assign component directly 
        ); 
    }; 
    

    このようにしてRouteのコンポーネントは更新の間に変更されません。

    preloadの引数は、propsです。これは実際には反パターンです。 propsにあなたが任意のコンポーネントの場合とちょうど標準的な方法渡すための適切な方法:

    const PreloadedFlagForm = preload(FlagForm) //drop the props arg 
    
    const FlagsApp = (props) => { 
        return (
         <Route path="/report/:reportId/flag/:id/edit" 
          component={<PreloadedFlagForm {...props} />} //spread it in here instead 
         /> 
        ); 
    }; 
    

    をだからpreloadのためのコードは次のようになります役立ちます

    export default function preload(WrappedComponent) { 
        class Preload extends React.Component { 
         componentWillMount() { 
          getDataForComponent(this.props); 
         } 
    
         render() { 
          return <WrappedComponent {...this.props} />; 
         } 
        } 
        return Preload; 
    } 
    

    願っています!

    0

    あなたが指示を読んでいない私のような場合は、答えは

    https://reacttraining.com/react-router/web/api/Route/render-func

    <Route>部品のrender小道具レンダリングにある:

    funcをこれは便利することができます上で説明した望ましくない再配置を行わずにインラインレンダリングとラッピングを行うことができます。

    ので、代わりにcomponent小道具にラッパー関数を渡すので、あなたはrender小道具を使用する必要があります。私は上記のようにやったしかし、あなたはラップのコンポーネントに渡すことはできません。私はまだこれが私の解決策だった、完全に何が起こっているのか分かりませんが、paramsを正しく受け継がれていることを確認します。私はそうのようにそれを使用

    マイプリロードラッパー関数は、現在のルートをレンダリングコンポーネントに反応さ

    ...

    export default class PreloadRoute extends React.Component { 
    
        static propTypes = { 
         preload: PropTypes.func.isRequired, 
         data: PropTypes.shape().isRequired, 
         location: PropTypes.shape({ 
          pathname: PropTypes.string.isRequired, 
         }), 
        } 
    
        componentWillMount() { 
         this.props.preload(this.props.data); 
        } 
    
        componentWillReceiveProps({ location = {}, preload, data }) { 
         const { location: prevLocation = {} } = this.props; 
    
         if (prevLocation.pathname !== location.pathname) { 
          preload(data); 
         } 
        } 
    
        render() { 
         return (
          <Route {...this.props} /> 
         ); 
        } 
    } 
    

    そして...

    const FlagsApp = (props) => { 
        return (
         <Switch> 
          <PreloadRoute exact path="/report/:reportId/flag/new" preload={showNewFlagForm} data={props} render={() => <FlagForm />} /> 
          <PreloadRoute exact path="/report/:reportId/flag/:id" preload={showFlag} data={props} render={() => <ViewFlag />} /> 
          <PreloadRoute path="/report/:reportId/flag/:id/edit" preload={showEditFlagForm} data={props} render={() => <FlagForm />} /> 
         </Switch> 
        ); 
    }; 
    

    私が呼んでいる理由移動するとき、私はその後、PreloadRoute部品の反対の問題が再マウントしていなかったので、componentWillMount中とcomponentWillReceiveProps両方this.props.preloadがあるので、これはそれを解決します。

    うまくいけば、この私は、文字通り、この作業は、ちょうど取得日を過ごしてきたように、当時の人々の多くの多くを保存します。それは私が推測する出血しているのコストです!

    関連する問題