Je n'ai vraiment pas obtenir la différence entre le rendu et la composante prop dans la Voie de réagir routeur, dans les docs il est dit que le rendu ne crée pas de nouvel élément, mais en composant, j'ai essayé de revenir à l'histoire, mais j'ai trouvé componentWillMount est appelé lorsque j'utilise le rendu en Route, que veulent-ils dire par "si vous fournissez une fonction en ligne de l'attribut de composant, vous devez créer un nouveau composant chaque rendu. Il en résulte existantes composant le démontage et le nouveau composant de montage au lieu de simplement mettre à jour le composant existant."
Réponses
Trop de publicités?Le code source indique la différence:
if (component)
return match ? React.createElement(component, props) : null
if (render)
return match ? render(props) : null
Lorsque vous utilisez component
- prop, le composant est instancié pour chaque appel d' Route#render
. Cela signifie que, pour votre composant que vous passez à l' component
prop de la Route, constructeur, componentWillMount
, et componentDidMount
sera exécuté à chaque fois que la route est rendu.
Par exemple, si vous avez
<Route path="/:locale/store" component={Store} />
et que l'utilisateur accède à /fr/magasin, puis s'en va ailleurs, et puis revient en arrière pour /fr/magasin, le magasin de composant sera monté, démonté, puis monté à nouveau. Il est similaire à ce
<Route path="/:locale/store">
<Store />
</Route>
Comparé à cela, si vous utilisez render
- prop, le composant est évalué sur chaque Route#render
. N'oubliez pas que chaque composant est une fonction? Cette fonction sera exécutée comme il est, sans aucun cycle de vie des méthodes. Ainsi, lorsque vous avez comme
<Route path="/:locale/store" render={Store} />
vous pouvez penser que
<Route path="/:locale/store">
{Store()}
</Route>
Il vous fait gagner de l'exécution, car pas de cycle de vie sont les méthodes de course, mais il a aussi un inconvénient dans le cas où Stocker le composant a quelques post-montage du cycle de vie des méthodes comme shouldComponentUpdate qui peut augmenter les performances.
Il y avait un bon poste sur Medium à propos de cette performance hack, veuillez jeter un oeil à elle. C'est très bien écrit et qui est applicable à Réagir 16, trop.
Donc, je suis confus sur cette section de docs en tant que bien, mais j'ai fini par le comprendre.
La clé pour comprendre cela est la déclaration de "fournir une fonction en ligne pour le composant prop"
Nous savons tous que la Route composant rendre à nouveau lorsque le lieu a changé, et de réagir permettra de comparer l'ancien et le nouveau virtuel arborescence DOM, obtenir des diff résultat et de l'appliquer à la vraie DOM.
Et de réagir vais essayer, il est préférable de réutiliser le nœud DOM, à moins que le type ou la clé prop de la nouvelle ReactElement est changé.
Donc
// 1.
const componentA = React.createElement(App, props)
const componentB = React.createElement(App, props)
console.log(componentA.type === componentB.type) // true
// 2.
const componentA = React.createElement(() => <App />, props)
const componentB = React.createElement(() => <App />, props)
console.log(componentA.type === componentB.type) // false
Tous les ReactElements créées par 1 ont le même type(App), mais ils n'ont pas le même type s'ils sont tous créés par 2.
Pourquoi?
Car il y a toujours une nouvelle fonction anonyme créée dans la voie 2 quand le parent du composant(Le composant qui contient Itinéraire composant) méthode render ai invoqué, de sorte que le type de nouvelles et anciennes ReactElement est à deux instances différentes de la fonction anonyme
() => <App />
Afin de Réagir de point de vue, il existe différents types d'élément et doit être traiter avec les démonter de vieux > installation de la nouvelle opération, cela signifie que chaque état ou les modifications que vous faites sur l'ancien composant eu de perte à chaque fois que le composant parent re-rendre.
Mais pourquoi le rendre prop éviter de le démonter et de monter comportement? C'est une fonction anonyme trop!?
Je voudrais ici pour consulter le code @Rishat Muhametshin posté, la partie centrale de la Route de la composante de la méthode de rendu:
if (component)
// We already know the differences:
// React.createElement(component)
// React.createElement(() => <component/>)
return match ? React.createElement(component, props) : null
if (render)
return match ? render(props) : null
rendre prop est une fonction qui retourne une ReactElement lorsqu'il est invoqué, quel est le type de l'élément retourné?
<Route render={() => <AppComponent />}></Route>
C'est AppComponent, pas la fonction anonyme emballage! Parce que, après jsx compilé:
render = () => React.createElement(AppComponent)
render() = React.createElement(AppComponent)
React.createElement(render) =
React.createElement(() => React.createElement(AppComponent))
React.createElement(render()) =
React.createElement(React.createElement(AppComponent))
Ainsi, lorsque vous utilisez rendu à la place de l'élément de support, le type d'élément que rendre prop de retour de la fonction ne va pas changer à chaque rendu, même il y a toujours une nouvelle fonction anonyme instance créée sur chaque parentElement.render()
Sur mon point de vue, vous pouvez obtenir le même comportement que le rendu prop ne avec le composant prop en donnant un nom à la fonction anonyme:
// Put this line outside render method.
const CreateAppComponent = () => <AppComponent />
// Inside render method
render(){
return <Route component={CreateAppComponent}/>
}
Donc la conclusion est, il n'y a pas de performance entre les différents composants et de rendre prop si vous utilisez le composant={AppComponent} directement, si vous souhaitez attribuer quelques accessoires pour AppComponent, l'utilisation
render={() => <AppComponent {...props}/> }
au lieu de component={() => <AppComponent {...props}/> }
La plupart des concepts ont été expliqués par d'autres réponses, Permettez-moi de faire le tri par la suite:
Tout d'abord, nous avons le code source:
if (component)
return match ? React.createElement(component, props) : null
if (render)
return match ? render(props) : null
cas n ° 1: composant sans fonction
<Route path="/create" component={CreatePage} />
React.createElement(CreatePage, props)
être appelé à cause de la React.createElement(component, props)
à partir du code source. L'instanciation serait la cause de la remonter.
cas n ° 2: rendre sans fonction
<Route path="/create" render={CreatePage} />
React.createElement(CreatePage, props)
a été appelé avant de passer en rendre prop, puis appelé par render(props)
à partir du code source. Aucune instanciation, pas de remontage.
cas n ° 3: composant avec la fonction
<Route path="/create" component={ () => <CreatePage /> } />
React.createElement(CreatePage, props)
être appelé deux fois. D'abord pour jsx l'analyse(fonction anonyme), d'Abord pour retourner une instance de CreatePage
de fonction anonyme, deuxième à partir du code source. Alors pourquoi ne pas le faire en composant prop.
Les erreurs de point par oligofren:
L'analyse de la JSX ne pas l'appeler. Elle se termine juste en haut de la création de la fonction d'expression. La raison pour laquelle vous ne voulez pas faire, #3, c'est que vous créez un nouveau type anonyme, à chaque fois, à l'origine de re-montage de la dom.
cas n ° 4: rendre avec la fonction
<Route path="/create" render={ () => <CreatePage /> } />
Il existe une instanciation(jsx analyse syntaxique) à chaque fois lors de l'acheminement d' path=/create
. Il se sent comme le cas n ° 1?
Conclusion
Selon les quatre cas, Si nous voulons passer prop pour Composant, nous avons besoin d'utiliser le cas n ° 4 pour prévenir le remontage.
<Route path="/abc" render={()=><TestWidget num="2" someProp={100}/>}/>
C'est un peu loin du sujet, alors je laisse le débat officiel pour plus de lecture.
Même si l'on ne passe pas tous les accessoires pour ComponentToRender
, j'ai trouvé quelques avantages de l'utilisation de rendu au lieu de composant.
Par défaut <Route \>
- passer supplémentaires accessoires({ history, location, match }
) à l' ComponentToRender
lors de l'utilisation de composant. Nous pouvons accéder à ce accessoires via le rendu de rappel, mais aussi on peut l'omettre.
Pourquoi avons-nous besoin? Chaque rendu de l' <Route />'s
société mère ou d'une de navigation(même si le changement de route de même qu'avant) créer de nouveaux match
objet.
Ainsi, lorsque nous la transmettons à nos ComponentToRender
, nous aurons de nouveaux accessoires de tous les temps, ce qui peut causer des problèmes de performances, surtout avec PureComponent
.