Analyse du quiz du concours React depuis le stand HeadHunter à HolyJs 2018

Salut Les 24 et 25 septembre, une conférence des développeurs frontaux de HolyJ a eu lieu à Moscou https://holyjs-moscow.ru/ . Nous sommes venus à la conférence avec notre stand sur lequel nous avons organisé un quiz. Il y avait un quiz principal - 4 tours de qualification et 1 tour final, sur lequel les constructeurs Apple Watch et lego ont été joués. Et séparément, nous avons mené un quiz sur les connaissances de React.


Sous cat - analyser les tâches du quiz sur réagir. Les bonnes options seront cachées sous le spoiler, vous pouvez donc non seulement lire l'analyse, mais aussi vous vérifier :)


image


C'est parti!


Pour plus de commodité, nous avons regroupé les questions en sections:


Section 1. Compréhension de base du fonctionnement de this.setState et mise à jour du cycle de vie des composants:


Question 1.


      react-: 1) SetProps, SetState, ForceUpdate 2) ForceUpdate, SetState 3) ForceUpdate, SetState, Parent (re)render 4) ForceUpdate, SetState, directly call UpdateComponent 

La réponse

3) ForceUpdate, SetState, Parent (re) render


Question 2.


  ,   this.setState({})  react 1)   ,  updating lifecycle 2)   ,    3) React    "Object cannot be empty" 4)    state   

La réponse

1) Le composant est marqué comme sale, la mise à jour du cycle de vie est appelée


Analyse des questions 1 et 2

Pour répondre à la question, nous analyserons 2 parties:
1) Propre demande de composant pour le cycle de mise à jour
2) Demande en dehors du composant


Le composant lui-même a 2 façons de se mettre à jour:
1) this.setState et this.forceUpdate. Dans ce cas, le composant sera marqué comme sale et sur la case Rapprochement, s'il est prioritaire pour le rendu, un cycle de mise à jour démarrera.


Fait intéressant: this.setState({}) et this.forceUpdate sont différents. Lorsque this.setState({}) est appelé, la boucle de mise à jour complète est appelée, contrairement à this.forceUpdate , lorsque la boucle de mise à jour démarre sans la méthode shouldComponentUpdate. Un exemple du travail de this.setState({}) peut être trouvé ici: https://codesandbox.io/s/m5jz2701l9 (si vous remplacez setState par forceUpdate dans l'exemple, vous pouvez voir comment le comportement des composants change).


2) Lorsque le parent du composant est restitué, il renvoie la partie vDOM, tous les enfants qui devront être mis à jour, et ils seront également appelés un cycle de vie de mise à jour complet. Un recomptage complet de la sous-arborescence peut être évité en décrivant shouldComponentUpdate ou en définissant le composant comme PureComponent.


Question 3


   Component  PureComponent (PC) 1) Component   ,    Pure 2) PC  SCU,  shallowEqual props  state 3) PC    ,    store 4)  PC    shouldComponentUpdate 

Réponse et analyse

2) Le PC implémente le SCU, conduit des accessoires peu profonds et indique


Comme nous l'avons vu précédemment, lors du (re) rendu du parent, la sous-arborescence entière sera envoyée au cycle de vie de mise à jour. Imaginez que vous avez mis à jour l'élément racine. Dans ce cas, selon l'effet de chaîne, vous devrez mettre à jour la quasi-totalité de l'arbre de réaction. Pour optimiser et ne pas envoyer de mises à jour inutiles, en réaction il existe une méthode shouldComponentUpdate , qui vous permet de retourner true si le composant doit être mis à jour, et false sinon. Pour simplifier les comparaisons dans PureComponent , vous pouvez hériter de PureComponent pour vous préparer immédiatement shouldComponentUpdate , qui compare par référence (s'il s'agit de types d'objet) ou par valeur (s'il s'agit de types de valeur) tous les accessoires et états qui entrent dans le composant.


Question 4.


 this.setState(() => {}, () => {}) —       setState? 1) set   .    updating 2)       state 3) setState   1  

Réponse et analyse

2) La deuxième fonction sera appelée après la mise à jour de l'état


Il existe deux méthodes dans le cycle de vie React: componentDidMount pour la boucle de montage et componentDidUpdate pour la mise à jour, où vous pouvez ajouter de la logique après la mise à jour du composant. Par exemple, faites une requête http, apportez des modifications stylistiques, obtenez des métriques des éléments html et (par condition) make setState. Si vous souhaitez effectuer une action après avoir modifié certains champs en état, alors dans la méthode componentDidUpdate , vous devrez écrire soit une comparaison:


 componentDidUpdate(prevProp, prevState) { if (prevState.foo !== this.state.foo) { // do awesome things here } } 

Ou vous pouvez le faire par setState:


 setState( // set new foo {foo: 'baz'}, () => { // do awesome things here } ); 

Chaque approche présente des avantages et des inconvénients (par exemple, si vous modifiez setState à plusieurs endroits, il peut être plus pratique d'écrire une condition une fois).


Question 5.


       render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' onClick={() => console.log('foo')} /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

La réponse

2) 2


Question 6.


       render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

La réponse

1) 1


Question 7.


       render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

La réponse

1) 1


Analyse des questions 5-7

Les questions 5 à 7 sont nécessaires pour la même chose - pour vérifier la compréhension du travail de PureComponent et la mise à jour des composants lors du transfert des accessoires. Si à l'intérieur de la méthode de rendu, nous passons un rappel jsx, le décrivant directement dans la fonction de rendu:


 render () { return <Button onClick={() => {}} />; } 

Ensuite, chaque rendu du parent mettra à jour le gestionnaire de clics donné. Cela se produit car chaque rendu crée une nouvelle fonction avec un lien unique, qui, comparé à PureComponent, montrera que les nouveaux accessoires ne sont pas égaux aux anciens et que vous devez mettre à jour le composant. Dans le cas où toutes les vérifications réussissent et que shouldComponentUpdate renvoie false, la mise à jour ne se produit pas.


Section 2. Clés dans React


Une analyse détaillée des clés que nous avons publiées ici: https://habr.com/company/hh/blog/352150/


Question 1.


     key,      ? 1)         key 2)    updating lifecycle 3)   key  4)    reconciliation 

Réponse et analyse

1) Supprimez l'instance précédente et montez la nouvelle lors du changement de clé


Sans utiliser de clé, react comparera la liste des éléments par paires de haut en bas. Si nous utilisons la clé, la comparaison se fera sur la clé correspondante. Si une nouvelle clé est apparue, un tel composant ne sera comparé à personne et sera immédiatement créé à partir de zéro.
Vous pouvez utiliser cette méthode même si nous avons 1 élément: nous pouvons définir <A key="1" /> , dans le prochain rendu, nous spécifierons <A key="2" /> et dans ce cas, <A key="2" /> supprimera <A key="1" /> et créez à partir de zéro <A key="2" /> .


Question 2.


       this.prop.key? 1)  2)  3)   static getKey 

Réponse et analyse

2) Non


Le composant peut apprendre la clé de ses enfants, qui lui ont été transmis comme accessoire, mais ne peut pas en savoir plus sur sa clé.


Question 3.


       render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A key='1' />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

Réponse et analyse

2) 2


Lors du changement de clé, le composant sera recréé, donc le rendu sera affiché deux fois.


Section 3. Questions sur jsx


Question 1.


   .           1)    prop / context 2)        3)  setParentProps 4)  static getParentRef 

Réponse et analyse

1) Rappel sous forme d'accessoire / contexte
2) Suppression de la couche du modèle et travail à travers elle


Il y a deux bonnes réponses. Le choix de l'un d'eux sur un quiz vous comptera des points. Cette question concerne la connaissance de la réaction du flux de données. Les données de haut en bas sont distribuées sous forme d'accessoires ou de contexte, elles peuvent contenir un rappel, que le composant ci-dessous peut appeler pour affecter l'état du système.
Une autre méthode combinant suppression de modèle, contexte et prop, est, par exemple, la liaison react-redux.
Cette bibliothèque prend un modèle dérivé de react (redux). Définit redux.store dans Provider, qui définit en fait le magasin dans son contexte. Ensuite, le développeur utilise la connexion HOC, qui va dans le contexte, s'abonne pour stocker (store.subscribe) les modifications, et lorsque le magasin change, raconte la fonction mapStateToProps . Si les données ont changé, il les définit dans les accessoires à l'objet encapsulé.
En même temps, connect vous permet de spécifier mapDispatchToProps , où le développeur spécifie les actionCreators qui doivent être transmis au composant. Nous, à leur tour, les recevons de l'extérieur (sans contexte), actionCreators les actionCreators au magasin (enveloppez-les dans store.dispatch) et passez-les en tant qu'accessoires au composant encapsulé.


Question 2.


   props   jsx?     1)   2)   children 

Réponse et analyse

1) Dans tout


Vous pouvez transférer à tout. Par exemple:


 <Button icon={<Icon kind='warning'/>}></Button> 

Dessine un bouton avec une icône. Cette approche est très pratique à utiliser afin de laisser au composant le droit de contrôler l'emplacement des différents éléments les uns par rapport aux autres, plutôt que de trier un accessoire enfant.


Section 4. Compréhension avancée de setState


Voici 3 questions fortement liées:


Question 1.


 this.state = {a: 'a'}; ... this.setState({a: 'b'}); this.setState({a: this.state.a + 1}) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3)   4) {a: 'a'} 

La réponse

3) Pas assez de données


Question 2.


 this.state={a: 'a'} ... this.setState({a: 'b'}) this.setState(state => ({a: state.a + 1})) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3)   4) {a: 'ab1'} 

La réponse

2) {a: 'b1'}


Question 3.


    2 setState  componentDidUpdate  updating lifecycle   1) 1 2) 2 3) 3 4)   

La réponse

1) 1


Analyse des questions 1-3

Tout le travail de setState est décrit en détail ici:
1) https://reactjs.org/docs/react-component.html#setstate
2) https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973#48610973


Le fait est que setState ne se produit pas de manière synchrone.
Et dans le cas où il y a plusieurs appels à setState d'affilée, selon que nous sommes à l'intérieur de la méthode react-lifecycle, la fonction de gestionnaire de l'événement react (onChange, onClick) ou non, l'exécution de setState dépend.
À l'intérieur des gestionnaires de réaction, setState fonctionne par lots (les modifications ne sont apportées qu'après que les fonctions définies par l'utilisateur dans la pile d'appels sont terminées et que nous entrons dans les fonctions qui appelaient notre gestionnaire d'événements et nos méthodes de cycle de vie). Ils roulent l'un après l'autre, donc si nous sommes à l'intérieur du gestionnaire de réaction, nous obtenons:


 this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' +   .       this.state.a // a: 'a' this.setState({a: this.state.a + 1}) // a: 'a1' 

depuis les changements ont eu lieu batchevo.
Mais en même temps, si setState a été appelé en dehors des gestionnaires de réaction:


 this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' +     this.state.a // a: 'b' this.setState({a: this.state.a + 1}) // a: 'b1' +     

Dans ce cas, les modifications seront apportées séparément.


Section 5. Redux


Question 1.


     action,  () => {} ? 1) .  action      type 2) ,   action      type 3) ,    middleware   action 4) ,       dispatch 

Réponse et analyse

3) Oui, vous devez définir un middleware personnalisé pour une telle action


Prenez redux-thunk comme exemple le plus simple. Tout middleware est un petit bloc de code:
https://github.com/reduxjs/redux-thunk/blob/master/src/index.js#L2-L9


 return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; 

Comment fonctionne le middleware?
Ils prennent le contrôle avant que l'action n'arrive au magasin. Par conséquent, une action qui a été remplacée passera d'abord par la chaîne du middleware.
Chaque middleware accepte une instance de magasin, la méthode suivante, qui vous permet de transmettre l'action plus loin, et l'action elle-même.
Si le middleware traite des actions personnalisées, telles que redux-thunk, alors si l'action est une fonction, il ne transmet pas l'action plus loin, mais la "noie", appelant plutôt l'action avec les méthodes dispatch et getState qui y sont passées.
Que se passerait-il si redux-thunk faisait ensuite l'action, ce qui est une fonction?
Avant d'appeler des réducteurs, store vérifie le type d'action. Il doit remplir les conditions suivantes:
1) Ce doit être un objet
2) Il doit avoir un champ type
3) Le champ type doit être de type chaîne


Si l'une des conditions n'est pas remplie, redux renvoie une erreur.


Questions bonus:


Question bonus 1.


   ? class Todos extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { return this.props.list.length - prevProps.list.length; } componentDidUpdate(a, b, c) { console.log(c); } ... } ReactDOM.render(<Todos list={['a','b']} />, app); setTimeout(() => ReactDOM.render(<Todos list={['a','b','a','b']} />, app), 0); a) 0 b) 1 c) 2 d) undefined 

Réponse et analyse

c) 2


getSnapshotBeforeUpdate est une fonction rarement utilisée dans react qui vous permet d'obtenir un instantané, qui sera ensuite transmis à componentDidUpdate. Cette méthode est nécessaire pour pré-calculer certaines données sur la base desquelles vous pouvez ensuite effectuer, par exemple, une demande de récupération.


Question bonus 2.


        2,5 ? function Input() { const [text, setText] = useState("World!"); useEffect( () => { let id = setTimeout(() => { setText("Hello " + text); }, 1000); return () => { clearTimeout(id); }; }, [text] ); return ( <input value={text} onChange={e => { setText(e.target.value); }} /> ); } a) "World!" b) "Hello World!" c) "Hello Hello World!" d)    

La réponse

c) "Bonjour, bonjour le monde!"


Il s'agit déjà de connaître de nouvelles fonctionnalités en réaction, ce n'était pas dans notre quiz. Essayons dans les commentaires de décrire en détail le fonctionnement du code de la dernière question :)

Source: https://habr.com/ru/post/fr431492/


All Articles