{"id":228527,"date":"2022-10-12T18:04:00","date_gmt":"2022-10-12T15:04:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228527"},"modified":"2022-11-09T02:52:02","modified_gmt":"2022-11-08T23:52:02","slug":"conversion-de-react-createclass-en-react-component","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/conversion-de-react-createclass-en-react-component\/","title":{"rendered":"Conversion de React.createClass en React.Component"},"content":{"rendered":"\n<p>Dans mon <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">dernier article, j&rsquo;ai parl\u00e9 de patcher les anciennes versions de React pour qu&rsquo;elles fonctionnent dans un environnement moderne<\/a>. Dans cet article, je vais un peu plus loin et donne un guide \u00e9tape par \u00e9tape pour mettre \u00e0 niveau un composant React classique vers un composant moderne, en changeant la <code>React.createClass<\/code>fa\u00e7on de faire les choses pour la m\u00e9thode moderne et pr\u00e9f\u00e9r\u00e9e <code>React.Component<\/code>.<\/p>\n<p>Les fichiers dont nous avons besoin se trouveront dans les dossiers \u00ab\u00a0Original\u00a0\u00bb et \u00ab\u00a0Final\u00a0\u00bb du r\u00e9pertoire des composants dans la solution GitHub qui l&rsquo;accompagne.<\/p>\n<p><a href=\"https:\/\/github.com\/mattwatsoncodes\/Tutorial-Convert-React-createClass-to-React-Component\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Obtenir des fichiers de didacticiel \u00e0 partir de GitHub<\/a><\/p>\n<p>Encore une fois travailler avec le composant <code>[react-checkbox-list](https:\/\/github.com\/sonyan\/react-checkbox-list)<\/code> <a href=\"https:\/\/github.com\/sonyan\/react-checkbox-list\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">de Sony An<\/a> (disponible comme <a href=\"https:\/\/www.npmjs.com\/package\/react-checkbox-list\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\"><code>react-checkbox-list<\/code>sur npm<\/a> ). Ce guide vous montre \u00e9tape par \u00e9tape comment remplacer la structure et les m\u00e9thodes d&rsquo;un composant classique par un <code>React.createClass<\/code>composant moderne <code>React.Component<\/code>.<\/p>\n<p>En commen\u00e7ant par le <code>.jsx<\/code>fichier dans la <code>react-checkbox-list<\/code>solution, nous allons d&rsquo;abord supprimer le <code>.js<\/code>fichier et le renommer <code>.js<\/code>car les <code>.jsx<\/code>fichiers n&rsquo;ont plus besoin d&rsquo;\u00eatre nomm\u00e9s diff\u00e9remment.<\/p>\n<p>Cela nous donne le code de d\u00e9marrage suivant\u00a0:<\/p>\n<pre><code>\n'use strict';\nvar React = require('react');\n\nmodule.exports = React.createClass({\n    displayName: 'CheckBoxList',\n\n    propTypes: {\n        defaultData: React.PropTypes.array,\n        onChange: React.PropTypes.func\n    },\n\n    getInitialState: function() {\n        return {\n            data: this.props.defaultData || []\n        };\n    },\n\n    handleItemChange: function(e) {\n        var selectedValues = [],\n            newData = [];\n\n        this.state.data.forEach(function(item) {\n            if(item.value === e.target.value) {\n                item.checked = e.target.checked;\n            }\n            if(item.checked) {\n                selectedValues.push(item.value);\n            }\n            newData.push(item);\n        });\n\n        this.setState({data: newData});\n\n        if(this.props.onChange) {\n            this.props.onChange(selectedValues);\n        }\n    },\n\n    reset: function() {\n        var newData = [];\n        this.state.data.forEach(function(item) {\n            item.checked = false;\n            newData.push(item);\n        });\n\n        this.setState({data: newData});\n    },\n\n    checkAll: function() {\n        var newData = [];\n        this.state.data.forEach(function(item) {\n            item.checked = true;\n            newData.push(item);\n        });\n\n        this.setState({data: newData});\n    },\n\n    render: function() {\n        var options;\n\n        options = this.state.data.map(function(item, index) {\n            return (&lt;div key={'chk-' + index} className=\"checkbox\"&gt;\n                    &lt;label&gt;\n                        &lt;input\n                            type=\"checkbox\"\n                            value={item.value}\n                            onChange={this.handleItemChange}\n                            checked={item.checked? true: false} \/&gt; {item.label}\n                    &lt;\/label&gt;\n                &lt;\/div&gt;\n            );\n        }.bind(this));\n\n        return (&lt;div&gt;\n                {options}\n            &lt;\/div&gt;\n        );\n    }\n});\n<\/code><\/pre>\n<h2>Conversion du composant<\/h2>\n<p>Lorsque vous essayez de charger ce code, la premi\u00e8re erreur que nous obtenons est<code>Uncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12<\/code><\/p>\n<p>Erreur non intercept\u00e9e\u00a0: \u00c9chec de la construction du module\u00a0: Erreur de syntaxe\u00a0: Le pragma <a href=\"https:\/\/hashnode.com\/@jsx\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@jsx<\/a> React.DOM est obsol\u00e8te depuis React 0.12<\/p>\n<p>Il est assez simple de corriger cela. Supprimez simplement la ligne <code>\/** @jsx React.DOM *\/<\/code>du haut du document.<\/p>\n<p>Nous obtenons maintenant la m\u00eame erreur <code>Uncaught TypeError: Cannot read property 'array' of undefined<\/code>que dans le <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">didacticiel sur les<\/a> <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">correctifs<\/a>. En effet, React.propTypes \u00e9tait obsol\u00e8te dans la version 15.50 de React. Par cons\u00e9quent, conform\u00e9ment \u00e0 ce didacticiel, continuez et installez le package PropTypes avec la commande via npm. Nous l&rsquo;importerons dans notre package plus tard.<code>[React.createClass](https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/)<\/code><a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external\"><\/a><\/p>\n<pre><code>npm install --save prop-types\n<\/code><\/pre>\n<p>Ce qui suit maintenant est une refonte compl\u00e8te de la base de code, nous ne pouvons donc pas actualiser et corriger une erreur comme nous l&rsquo;avons peut-\u00eatre fait pr\u00e9c\u00e9demment, nous ne saurons donc pas si cela a fonctionn\u00e9 jusqu&rsquo;\u00e0 la toute fin. Bouclez votre ceinture\u00a0!<\/p>\n<p>Commen\u00e7ons par remplacer la <code>React.createClass<\/code>fonction en d\u00e9clarant un new <code>React.Component<\/code>. Modifiez notre code pour qu&rsquo;il ressemble \u00e0 ceci\u00a0:<\/p>\n<pre><code>'use strict';\nimport React from 'react';\n\nclass CheckBoxList extends React.Component {\n...\n}\n<\/code><\/pre>\n<p>Notez que nous avons fait quelques choses ici :<\/p>\n<ul>\n<li>Suppression du commentaire d&rsquo;ouverture JSX<\/li>\n<li>Modifi\u00e9 le type de d\u00e9claration de <code>var React =...<\/code>\u00e0 <code>import React from 'react';<\/code>c&rsquo;est la fa\u00e7on moderne de faire des d\u00e9clarations dans React.<\/li>\n<li>Nous d\u00e9clarons maintenant une nouvelle classe de <code>CheckBoxList<\/code>, au lieu d&rsquo;exporter une fonction.<\/li>\n<li>En raison de la syntaxe de l&rsquo;objet maintenant entre parenth\u00e8ses, <code>{...}<\/code>nous devons supprimer la fermeture<code>);<\/code><\/li>\n<\/ul>\n<p>Cependant, il manque maintenant \u00e0 cette nouvelle classe un moyen d&rsquo;\u00eatre export\u00e9e afin que d&rsquo;autres composants puissent l&rsquo;utiliser, alors ajoutons une d\u00e9claration d&rsquo;exportation au bas de ce code.<\/p>\n<pre><code>'use strict';\nimport React from 'react';\n\nclass CheckBoxList extends React.Component {\n...\n}\n\nexport default CheckBoxList;\n<\/code><\/pre>\n<p>Dans notre code d&rsquo;origine, la premi\u00e8re ligne de code de la fonction \u00e9tait <code>displayName: 'CheckBoxList',<\/code>notre exportation qui g\u00e8re maintenant cela, nous pouvons donc supprimer compl\u00e8tement ce code.<\/p>\n<p>La ligne suivante d\u00e9clare que ceux- <code>propTypes<\/code>ci se trouvent maintenant en dehors de la classe et ont besoin de la <code>PropTypes<\/code>d\u00e9pendance que nous avons ajout\u00e9e via npm. Ajoutons cela dans nos importations et \u00e9crivons les PropTypes comme suit\u00a0:<\/p>\n<pre><code>'use strict';\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nclass CheckBoxList extends React.Component {\n...\n}\n\nCheckBoxList.propTypes = {\n    defaultData: PropTypes.array,\n    onChange: PropTypes.func,\n};\n\nexport default CheckBoxList;\n<\/code><\/pre>\n<p>Ensuite, l&rsquo;\u00e9tat est d\u00e9clar\u00e9 via la m\u00e9thode <code>getInitialState<\/code>avec <code>React.Component<\/code>nous d\u00e9finissons notre \u00e9tat initial avec un constructeur. Ajoutez le code suivant dans notre build\u00a0:<\/p>\n<pre><code>...\nclass CheckBoxList extends React.Component {\n    constructor( props) {\n        super( props );\n        this.state = {\n            data: [],\n        }\n    }\n...\n}\n...\n<\/code><\/pre>\n<p>Voil\u00e0, cela d\u00e9finit l&rsquo;\u00e9tat du composant, mais attendez, nous ne lui avons pas dit d&rsquo;o\u00f9 il devait obtenir son \u00e9tat. C&rsquo;est l\u00e0 que \u00e7a <code>componentWillMount<\/code>devient pratique.<\/p>\n<pre><code>...\nclass CheckBoxList extends React.Component {\n    constructor( props) {\n        super( props );\n        this.state = {\n            data: [],\n        }\n    }\n\n    componentWillMount() {\n        this.setState({\n            data: this.props.defaultData,\n        });\n    }\n...\n}\n...\n<\/code><\/pre>\n<p>Une chose importante \u00e0 noter est que les m\u00e9thodes internes de <code>React.Component<\/code>ne se terminent pas par des virgules (<code>,<\/code>), alors assurez-vous que toutes les m\u00e9thodes que vous ajoutez au composant ne se terminent pas par une virgule !<\/p>\n<p>Ensuite, rajoutons la fonction de rendu. C&rsquo;est probablement la partie la plus simple, c&rsquo;est presque la m\u00eame chose, avec la diff\u00e9rence cl\u00e9 que nous changeons <code>render: function() {<\/code>en juste <code>render() {<\/code>.<\/p>\n<pre><code>...\nclass CheckBoxList extends React.Component {\n...\n    render() {\n        var options;\n\n        options = this.state.data.map(function(item, index) {\n            return (&lt;div key={'chk-' + index} className=\"checkbox\"&gt;\n                    &lt;label&gt;\n                        &lt;input\n                            type=\"checkbox\"\n                            value={item.value}\n                            onChange={this.handleItemChange}\n                            checked={item.checked? true: false} \/&gt; {item.label}\n                    &lt;\/label&gt;\n                &lt;\/div&gt;\n            );\n        }.bind(this));\n\n        return (&lt;div&gt;\n                {options}\n            &lt;\/div&gt;\n        );\n    }\n...\n}\n...\n<\/code><\/pre>\n<p>Dans le but de garder ce tutoriel au point, je ne convertirai pas les deux m\u00e9thodes <code>reset<\/code>et <code>checkAll<\/code>cependant les concepts utilis\u00e9s pour le port de la m\u00e9thode <code>handleItemChange<\/code>apple aux deux, alors n&rsquo;h\u00e9sitez pas \u00e0 les essayer vous-m\u00eame.<\/p>\n<p>Pour migrer la <code>handleItemChange<\/code>m\u00e9thode, nous devons d&rsquo;abord supprimer la virgule fermante (<code>,<\/code>) et modifier le type de d\u00e9claration de fonction de <code>handleItemChange: function(e) {<\/code>pour <code>handleItemChange( e) {<\/code>nous assurer que nous le transmettons toujours <code>e<\/code>en tant que param\u00e8tre d&rsquo;\u00e9v\u00e9nement.<\/p>\n<p>Ajoutons cela au-dessus de notre m\u00e9thode de rendu.<\/p>\n<pre><code>...\nclass CheckBoxList extends React.Component {\n...\n    handleItemChange( e) {\n        var selectedValues = [],\n            newData = [];\n\n        this.state.data.forEach(function(item) {\n            if(item.value == e.target.value) {\n                item.checked = e.target.checked;\n            }\n            if(item.checked) {\n                selectedValues.push(item.value);\n            }\n            newData.push(item);\n        });\n\n        this.setState( {data: newData} );\n\n        if(this.props.onChange) {\n            this.props.onChange(selectedValues);\n        }\n    }\n...\n}\n...\n<\/code><\/pre>\n<p>Notre composant va maintenant \u00eatre rendu, mais il ne sera pas fonctionnel. Lorsque vous essayez de cliquer sur une case \u00e0 cocher, vous obtenez l&rsquo;erreur <code>Uncaught TypeError: Cannot read property 'state' of undefined<\/code>.<\/p>\n<p>Erreur de type non intercept\u00e9e\u00a0: impossible de lire la propri\u00e9t\u00e9 &lsquo;\u00e9tat&rsquo; de undefined<\/p>\n<p>C&rsquo;est parce que dans notre <code>handleItemChange<\/code>m\u00e9thode, o\u00f9 nous essayons d&rsquo;acc\u00e9der \u00e0 l&rsquo;\u00e9tat, <code>this<\/code>n&rsquo;est pas d\u00e9fini. Pour r\u00e9soudre ce probl\u00e8me, nous devons lier notre fonction \u00e0 <code>this<\/code>en ajoutant la ligne suivante dans notre constructeur\u00a0: <code>this.handleItemChange = this.handleItemChange.bind( this );<\/code>.<\/p>\n<pre><code>...\nclass CheckBoxList extends React.Component {\n    constructor( props) {\n        super( props );\n        this.state = {\n            data: [],\n        }\n        this.handleItemChange = this.handleItemChange.bind( this );\n    }\n...\n}\n...\n<\/code><\/pre>\n<p>Et voil\u00e0, notre composant React nouvellement converti en action.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-169430-61e80f22b2772.gif\" alt=\"Conversion de React.createClass en React.Component\" \/>React.createClass \u00e0 React.Component<\/p>\n<h2>Code source du didacticiel<\/h2>\n<p>Vous pouvez <a href=\"https:\/\/github.com\/wholesomecode\/Tutorial-Convert-React-createClass-to-React-Component\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e9l\u00e9charger le code source de la version originale et finale du composant sur GitHub<\/a>. Le plugin contient un bloc WordPress Gutenberg que vous pouvez utiliser pour jouer avec le code, avec trois fichiers que vous pouvez supprimer selon le cas :<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-169430-61e80f247b7d4.png\" alt=\"Conversion de React.createClass en React.Component\" \/>Les fichiers du didacticiel GitHub pour la conversion de React.createClass en React.Component<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/wholesomecode.ltd\" class=\"external external_icon\">wholesomecode.ltd<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dans mon dernier article, j&rsquo;ai parl\u00e9 de patcher les anciennes versions de React pour fonctionner dans un environnement moderne. Dans cet article, je vais un peu plus loin et donne un guide \u00e9tape par \u00e9tape pour mettre \u00e0 niveau un cl &#8230;<\/p>\n","protected":false},"author":1,"featured_media":224207,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[915,893,717,841],"tags":[1167],"class_list":["post-228527","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-autre","category-code-2","category-developpeur","category-tutoriels","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/228527","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=228527"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/228527\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/224207"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=228527"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=228527"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=228527"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}