{"id":228079,"date":"2022-10-12T18:40:00","date_gmt":"2022-10-12T15:40:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228079"},"modified":"2022-11-09T00:36:28","modified_gmt":"2022-11-08T21:36:28","slug":"konwersja-react-createclass-do-react-component","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/konwersja-react-createclass-do-react-component\/","title":{"rendered":"Konwersja React.createClass do React.Component"},"content":{"rendered":"\n<p>W moim <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ostatnim artykule m\u00f3wi\u0142em o \u0142ataniu starszych wersji Reacta, aby dzia\u0142a\u0142y w nowoczesnym \u015brodowisku<\/a>. W tym artykule id\u0119 krok po kroku i krok po kroku, jak uaktualni\u0107 klasyczny komponent React do nowoczesnego, zmieniaj\u0105c <code>React.createClass<\/code>spos\u00f3b robienia rzeczy na nowoczesn\u0105 i preferowan\u0105 <code>React.Component<\/code>metod\u0119.<\/p>\n<p>Potrzebne nam pliki b\u0119d\u0105 znajdowa\u0107 si\u0119 w folderach \u201eOriginal&quot; i \u201eFinal&#8221; katalogu komponent\u00f3w w towarzysz\u0105cym rozwi\u0105zaniu GitHub.<\/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\">Pobierz pliki samouczka z GitHub<\/a><\/p>\n<p>Znowu praca z komponentem <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\">Sony An<\/a> (dost\u0119pny jak <a href=\"https:\/\/www.npmjs.com\/package\/react-checkbox-list\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\"><code>react-checkbox-list<\/code>na npm<\/a> ). Ten przewodnik pokazuje krok po kroku, jak zast\u0105pi\u0107 konstrukcj\u0119 i metody klasycznego <code>React.createClass<\/code>komponentu nowoczesnym <code>React.Component<\/code>.<\/p>\n<p>Zaczynaj\u0105c od <code>.jsx<\/code>pliku w <code>react-checkbox-list<\/code>rozwi\u0105zaniu, najpierw usuniemy <code>.js<\/code>plik i zmienimy jego nazw\u0119, <code>.js<\/code>poniewa\u017c <code>.jsx<\/code>pliki nie musz\u0105 ju\u017c mie\u0107 innych nazw.<\/p>\n<p>To daje nam nast\u0119puj\u0105cy kod startowy:<\/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>Konwersja komponentu<\/h2>\n<p>Podczas pr\u00f3by za\u0142adowania tego kodu pierwszym b\u0142\u0119dem, jaki otrzymujemy, jest<code>Uncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12<\/code><\/p>\n<p>Nieprzechwycony b\u0142\u0105d: Budowa modu\u0142u nie powiod\u0142a si\u0119: SyntaxError: <a href=\"https:\/\/hashnode.com\/@jsx\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Pragma @jsx<\/a> React.DOM zosta\u0142a uznana za przestarza\u0142\u0105 w React 0.12<\/p>\n<p>\u0141atwo to naprawi\u0107. Po prostu usu\u0144 lini\u0119 <code>\/** @jsx React.DOM *\/<\/code>z g\u00f3ry dokumentu.<\/p>\n<p>Otrzymujemy teraz ten <code>Uncaught TypeError: Cannot read property 'array' of undefined<\/code>sam b\u0142\u0105d, co w <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">samouczku dotycz\u0105cym<\/a> <a href=\"https:\/\/wholesomecode.ltd\/blog\/broken-react-createclass-component-lets-fix-it\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u0142atania<\/a>. Dzieje si\u0119 tak dlatego, \u017ce React.propTypes by\u0142 przestarza\u0142y w wersji React 15.50, wi\u0119c zgodnie z tym samouczkiem zainstaluj pakiet PropTypes za pomoc\u0105 polecenia przez npm. Zaimportujemy to p\u00f3\u017aniej do naszego pakietu.<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>To, co nast\u0119puje teraz, to kompletna przebudowa bazy kodu, wi\u0119c nie mo\u017cemy od\u015bwie\u017cy\u0107 i naprawi\u0107 b\u0142\u0119du, jak mogli\u015bmy to zrobi\u0107 wcze\u015bniej, wi\u0119c nie b\u0119dziemy wiedzie\u0107, czy zadzia\u0142a\u0142o to do samego ko\u0144ca. Bra\u0107 si\u0119 do rzeczy!<\/p>\n<p>Zacznijmy od zast\u0105pienia <code>React.createClass<\/code>funkcji przez zadeklarowanie nowego <code>React.Component<\/code>. Zmie\u0144 nasz kod tak, aby wygl\u0105da\u0142 nast\u0119puj\u0105co:<\/p>\n<pre><code>'use strict';\nimport React from 'react';\n\nclass CheckBoxList extends React.Component {\n...\n}\n<\/code><\/pre>\n<p>Zauwa\u017c, \u017ce zrobili\u015bmy tutaj kilka rzeczy:<\/p>\n<ul>\n<li>Usuni\u0119to otwieraj\u0105cy komentarz JSX<\/li>\n<li>Zmieniony typ deklaracji z <code>var React =...<\/code>na <code>import React from 'react';<\/code>ten to nowoczesny spos\u00f3b sk\u0142adania deklaracji w React.<\/li>\n<li>Teraz deklarujemy now\u0105 klas\u0119 <code>CheckBoxList<\/code>, zamiast eksportowa\u0107 funkcj\u0119.<\/li>\n<li>Ze wzgl\u0119du na sk\u0142adni\u0119 obiektu, kt\u00f3ry jest teraz uj\u0119ty w nawias <code>{...}<\/code>, musimy usun\u0105\u0107 zamkni\u0119cie<code>);<\/code><\/li>\n<\/ul>\n<p>Jednak tej nowej klasie brakuje teraz sposobu na wyeksportowanie jej, aby inne komponenty mog\u0142y z niej korzysta\u0107, wi\u0119c dodajmy deklaracj\u0119 eksportu na dole tego kodu.<\/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>W naszym oryginalnym kodzie, pierwszy wiersz kodu w funkcji by\u0142 <code>displayName: 'CheckBoxList',<\/code>naszym eksportem, teraz obs\u0142uguje to, wi\u0119c mo\u017cemy ca\u0142kowicie usun\u0105\u0107 ten kod.<\/p>\n<p>Nast\u0119pna linia ni\u017cej deklaruje, \u017ce <code>propTypes<\/code>te znajduj\u0105 si\u0119 teraz poza klas\u0105 i potrzebuj\u0105 <code>PropTypes<\/code>zale\u017cno\u015bci, kt\u00f3r\u0105 dodali\u015bmy przez npm. Dodajmy to do naszego importu i napiszmy PropTypes w ten spos\u00f3b:<\/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>Nast\u0119pnie stan jest deklarowany za pomoc\u0105 metody, <code>getInitialState<\/code>w <code>React.Component<\/code>kt\u00f3rej ustawiamy nasz stan pocz\u0105tkowy za pomoc\u0105 konstruktora. Dodaj nast\u0119puj\u0105cy kod do naszej kompilacji:<\/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>No i zaczynamy, ustawiamy stan komponentu, ale poczekaj, nie powiedzieli\u015bmy mu, sk\u0105d wzi\u0105\u0107 jego stan. To <code>componentWillMount<\/code>si\u0119 przydaje.<\/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>Kluczow\u0105 rzecz\u0105 do zapami\u0119tania jest to, \u017ce wewn\u0119trzne metody <code>React.Component<\/code>nie ko\u0144cz\u0105 si\u0119 przecinkami (<code>,<\/code>), wi\u0119c upewnij si\u0119, \u017ce metody dodane do komponentu nie ko\u0144cz\u0105 si\u0119 przecinkiem!<\/p>\n<p>Nast\u0119pnie dodajmy z powrotem funkcj\u0119 render. To prawdopodobnie naj\u0142atwiejsza cz\u0119\u015b\u0107, jest prawie taka sama, z kluczow\u0105 r\u00f3\u017cnic\u0105, kt\u00f3r\u0105 zmieniamy <code>render: function() {<\/code>na just <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>Aby utrzyma\u0107 ten samouczek na temat, nie b\u0119d\u0119 konwertowa\u0107 dw\u00f3ch metod <code>reset<\/code>i <code>checkAll<\/code>poj\u0119\u0107 u\u017cywanych do przeniesienia metody <code>handleItemChange<\/code>apple na obie, wi\u0119c mo\u017cesz spr\u00f3bowa\u0107 samemu.<\/p>\n<p>Aby przeprowadzi\u0107 migracj\u0119 <code>handleItemChange<\/code>metody, najpierw musimy usun\u0105\u0107 zamykaj\u0105cy przecinek (<code>,<\/code>) i zmieni\u0107 typ deklaracji funkcji z <code>handleItemChange: function(e) {<\/code>na <code>handleItemChange( e) {<\/code>upewniaj\u0105c si\u0119, \u017ce nadal przekazujemy <code>e<\/code>jako parametr zdarzenia.<\/p>\n<p>Dodajmy to powy\u017cej naszej metody renderowania.<\/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>Nasz komponent b\u0119dzie si\u0119 teraz renderowa\u0142, ale nie b\u0119dzie dzia\u0142a\u0142. Gdy spr\u00f3bujesz klikn\u0105\u0107 pole wyboru, pojawi si\u0119 b\u0142\u0105d <code>Uncaught TypeError: Cannot read property 'state' of undefined<\/code>.<\/p>\n<p>Nieprzechwycony b\u0142\u0105d typu: nie mo\u017cna odczyta\u0107 w\u0142a\u015bciwo\u015bci \u201estan&#8221; niezdefiniowanej<\/p>\n<p>Dzieje si\u0119 tak, poniewa\u017c w naszej <code>handleItemChange<\/code>metodzie, w kt\u00f3rej pr\u00f3bujemy uzyska\u0107 dost\u0119p do stanu, <code>this<\/code>jest on niezdefiniowany. Aby to naprawi\u0107, musimy powi\u0105za\u0107 nasz\u0105 funkcj\u0119 <code>this<\/code>, dodaj\u0105c nast\u0119puj\u0105cy wiersz do naszego konstruktora: <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>I oto mamy to, nasz nowo przekonwertowany komponent React w akcji.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-169430-61e80f22b2772.gif\" alt=\"Konwersja React.createClass do React.Component\" \/>React.createClass do React.Component<\/p>\n<h2>Kod \u017ar\u00f3d\u0142owy samouczka<\/h2>\n<p>Mo\u017cesz <a href=\"https:\/\/github.com\/wholesomecode\/Tutorial-Convert-React-createClass-to-React-Component\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">pobra\u0107 kod \u017ar\u00f3d\u0142owy oryginalnej i ostatecznej wersji komponentu z serwisu GitHub<\/a>. Wtyczka zawiera blok WordPress Gutenberg, kt\u00f3rego mo\u017cesz u\u017cy\u0107 do zabawy z kodem, z trzema plikami, kt\u00f3re mo\u017cesz usun\u0105\u0107, je\u015bli dotyczy:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-169430-61e80f247b7d4.png\" alt=\"Konwersja React.createClass do React.Component\" \/>Pliki samouczka GitHub dla React.createClass do konwersji React.Component<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/wholesomecode.ltd\" class=\"external external_icon\">wholesomecode.ltd<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>W moim ostatnim artykule m\u00f3wi\u0142em o \u0142ataniu starszych wersji Reacta, aby dzia\u0142a\u0142y w nowoczesnym \u015brodowisku. W tym artykule id\u0119 o krok dalej i podaj\u0119 krok po kroku, jak ulepszy\u0107 kl&#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":[721,919,897,845],"tags":[1169],"class_list":["post-228079","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-inny","category-kod","category-samouczki","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/228079","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=228079"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/228079\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/224207"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=228079"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=228079"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=228079"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}