Несколько практических советов для улучшения качества кода. Обсудить Статья публикуется в переводе, автор оригинального текста Мохаммад Фейсал. React очень лоялен к тому, что и как мы пишем и как организуем свой код. Поэтому ответственность за поддержание чистоты и качества наших проектов несем только мы. Сегодня поговорим о том, как это сделать, – о самых полезных практиках разработки на React. 1. Используйте JSX-сокращения Использовать логические значения никогда не было так просто. Допустим, вам нужно управлять видимостью компонента Navbar – с помощью пропса showTitle: Плохо return ( <Navbar showTitle={true} /> ); Хорошо return( <Navbar showTitle /> ) 2. Используйте тернарные операторы Отличный способ для выбора между двумя компонентами по некоторому условию – например, в зависимости от роли активного пользователя. Плохо const { role } = user; if(role === ADMIN) { return <AdminUser /> }else{ return <NormalUser /> } Хорошо const { role } = user; return role === ADMIN ? <AdminUser /> : <NormalUser /> 3. Используйте преимущества объектных литералов Если у вас выбор между тремя и более компонентами, тернарный оператор не подходит. В этом случае литералы объектов могут сделать код более читаемым – используйте их вместо сложных условий. Плохо const {role} = user switch(role){ case ADMIN: return <AdminUser /> case EMPLOYEE: return <EmployeeUser /> case USER: return <NormalUser /> } Хорошо const {role} = user const components = { ADMIN: AdminUser, EMPLOYEE: EmployeeUser, USER: NormalUser }; const Component = components[role]; return <Component />; 4. Используйте фрагменты Нет никакого преимущества в использовании div вместо Fragment. Зачем вам нужен лишний элемент в виртуальном DOM? Плохо return ( <div> <Component1 /> <Component2 /> <Component3 /> </div> ) Хорошо return ( <> <Component1 /> <Component2 /> <Component3 /> </> ) 5. Не определяйте функцию внутри рендера Старайтесь не смешивать логику и рендер внутри компонента. Плохо return ( <button onClick={() => dispatch(ACTION_TO_SEND_DATA)}> // NOTICE HERE This is a bad example </button> ) Хорошо const submitData = () => dispatch(ACTION_TO_SEND_DATA) return ( <button onClick={submitData}> This is a good example </button> ) 6. Используйте Memo React.PureComponent и Memo могут значительно повысить производительность вашего приложения, позволяя избежать ненужного рендеринга. Плохо import React, { useState } from "react"; export const TestMemo = () => { const [userName, setUserName] = useState("faisal"); const [count, setCount] = useState(0); const increment = () => setCount((count) => count + 1); return ( <> <ChildrenComponent userName={userName} /> <button onClick={increment}> Increment </button> </> ); }; const ChildrenComponent =({ userName }) => { console.log("rendered", userName); return <div> {userName} </div>; }; Дочерний компонент должен отображаться только один раз, так как значение count не имеет к нему никакого отношения. И тем не менее он рендерится при каждом нажатии на кнопку. https://miro.medium.com/max/700/1*UC19Qvfj06VAy63lR8mOFg.png Хорошо Отредактируем немного ChildrenComponent: import React ,{useState} from "react"; const ChildrenComponent = React.memo(({userName}) => { console.log('rendered') return <div> {userName}</div> }) Теперь не имеет значения, сколько раз пользователь кликнет на кнопку, компонент отрендерится только при необходимости. 7. Перенесите CSS в JavaScript Организовать CSS сложнее, чем JavaScript, но можно постараться. Плохо // CSS файл .body { height: 10px; } // JSX return <div className='body'> </div> Хорошо const bodyStyle = { height: "10px" } return <div style={bodyStyle}> </div> 8. Используйте деструктуризацию объектов Одна из новейших возможностей JS сделает ваш код более читаемым. Плохо return ( <> <div> {user.name} </div> <div> {user.age} </div> <div> {user.profession} </div> </> ) Хорошо const { name, age, profession } = user; return ( <> <div> {name} </div> <div> {age} </div> <div> {profession} </div> </> ) 9. Строковые пропсы без фигурных скобок Передать строковые данные проще, чем вы думаете. Плохо return( <Navbar title={"My Special App"} /> ) Хорошо return( <Navbar title="My Special App" /> ) 10. Удалите JS из JSX Уберите весь код JavaScript из JSX-разметки, если он не служит какой-либо цели рендеринга или функциональности UI. Плохо return ( <ul> {posts.map((post) => ( <li onClick={event => { console.log(event.target, 'clicked!'); // <- THIS IS BAD }} key={post.id}>{post.title} </li> ))} </ul> ); Хорошо const onClickHandler = (event) => { console.log(event.target, 'clicked!'); } return ( <ul> {posts.map((post) => ( <li onClick={onClickHandler} key={post.id}> {post.title} </li> ))} </ul> ); 11. Строковые литералы Используйте строковые литералы вместо громоздкой конкатенации строк. Плохо const userDetails = user.name + "'s profession is" + user.proffession return ( <div> {userDetails} </div> ) Хорошо const userDetails = `${user.name}'s profession is ${user.proffession}` return ( <div> {userDetails} </div> ) 12. Порядок импортов Старайтесь импортировать модули в определенном порядке, чтобы сделать код более логичным. Плохо import React from 'react'; import ErrorImg from '../../assets/images/error.png'; import styled from 'styled-components/native'; import colors from '../../styles/colors'; import { PropTypes } from 'prop-types'; Хорошо Эмпирическое правило заключается в следующем порядке импорта: сначала встроенные (build-in) модули; затем внешние; и наконец внутренние. import React from 'react'; import { PropTypes } from 'prop-types'; import styled from 'styled-components/native'; import ErrorImg from '../../assets/images/error.png'; import colors from '../../styles/colors'; 13. Используйте неявный return Неявный возврат делает ваши функции изящнее. Но не злоупотребляйте этой фичей, она уместна только в простых функциях. Плохо const add = (a, b) => { return a + b; } Хорошо const add = (a, b) => a + b; 14. Именование компонентов Всегда используйте PascalCase для имен компонентов и camelCase – для экземпляров. Плохо import reservationCard from './ReservationCard'; const ReservationItem = <ReservationCard />; Хорошо import ReservationCard from './ReservationCard'; const reservationItem = <ReservationCard />; 15. Зарезервированные имена свойств Не используйте зарезервированные имена атрибутов для передачи пропсов, другие разработчики могут быть к этому не готовы. Плохо <MyComponent style="dark" /> <MyComponent className="dark" /> Хорошо <MyComponent variant="fancy" /> 16. Кавычки Используйте двойные кавычки для атрибутов JSX и одинарные – для всего остального кода JavaScript. Плохо <Foo bar='bar' /> <Foo style={{ left: "20px" }} /> Хорошо <Foo bar="bar" /> <Foo style={{ left: '20px' }} /> 17. Именование пропсов Всегда используйте camelCase для имен пропсов или PascalCase, если значение атрибута – это другой React-компонент. Плохо <Component UserName="hello" phone_number={12345678} /> Хорошо <MyComponent userName="hello" phoneNumber={12345678} Component={SomeComponent} /> 18. JSX в скобках Если ваш компонент занимает больше, чем одну строчку, всегда оборачивайте его в скобки. Плохо return <MyComponent variant="long"> <MyChild /> </MyComponent>; Хорошо return ( <MyComponent variant="long"> <MyChild /> </MyComponent> ); 19. Самозакрывающиеся теги Если у вашего компонента нет дочерних элементов, используйте самозакрывающийся тег для улучшения читаемости. Плохо <SomeComponent variant="stuff"></SomeComponent> Хорошо <SomeComponent variant="stuff" /> 20. Подчеркивание в именах методов Не используйте подчеркивание в любых внутренних методах. Плохо const _onClickHandler = () => { // do stuff } Хорошо const onClickHandler = () => { // do stuff } 21. Атрибут alt Всегда устанавливайте атрибут alt для теги img и не используйте в нем слова image и picture. Альтернативный текст предназначен для скринридеров, которые и так объявляют элемент как изображение, зачем повторяться? Плохо <img src="hello.jpg" /> <img src="hello.jpg" alt="Picture of me rowing a boat" /> Хорошо <img src="hello.jpg" alt="Me waving hello" /> Заключение Вот и все. Поздравляем, если вы зашли так далеко! Надеюсь, вы кое-что узнали из этой статьи.
Статья публикуется в переводе, автор оригинального текста Мохаммад Фейсал.
React очень лоялен к тому, что и как мы пишем и как организуем свой код. Поэтому ответственность за поддержание чистоты и качества наших проектов несем только мы.
Сегодня поговорим о том, как это сделать, – о самых полезных практиках разработки на React.
Использовать логические значения никогда не было так просто. Допустим, вам нужно управлять видимостью компонента Navbar – с помощью пропса showTitle:
Navbar
showTitle
Плохо
return ( <Navbar showTitle={true} /> );
Хорошо
return( <Navbar showTitle /> )
Отличный способ для выбора между двумя компонентами по некоторому условию – например, в зависимости от роли активного пользователя.
const { role } = user; if(role === ADMIN) { return <AdminUser /> }else{ return <NormalUser /> }
const { role } = user; return role === ADMIN ? <AdminUser /> : <NormalUser />
Если у вас выбор между тремя и более компонентами, тернарный оператор не подходит. В этом случае литералы объектов могут сделать код более читаемым – используйте их вместо сложных условий.
const {role} = user switch(role){ case ADMIN: return <AdminUser /> case EMPLOYEE: return <EmployeeUser /> case USER: return <NormalUser /> }
const {role} = user const components = { ADMIN: AdminUser, EMPLOYEE: EmployeeUser, USER: NormalUser }; const Component = components[role]; return <Component />;
Нет никакого преимущества в использовании div вместо Fragment. Зачем вам нужен лишний элемент в виртуальном DOM?
div
Fragment
return ( <div> <Component1 /> <Component2 /> <Component3 /> </div> )
return ( <> <Component1 /> <Component2 /> <Component3 /> </> )
Старайтесь не смешивать логику и рендер внутри компонента.
return ( <button onClick={() => dispatch(ACTION_TO_SEND_DATA)}> // NOTICE HERE This is a bad example </button> )
const submitData = () => dispatch(ACTION_TO_SEND_DATA) return ( <button onClick={submitData}> This is a good example </button> )
React.PureComponent и Memo могут значительно повысить производительность вашего приложения, позволяя избежать ненужного рендеринга.
React.PureComponent
Memo
import React, { useState } from "react"; export const TestMemo = () => { const [userName, setUserName] = useState("faisal"); const [count, setCount] = useState(0); const increment = () => setCount((count) => count + 1); return ( <> <ChildrenComponent userName={userName} /> <button onClick={increment}> Increment </button> </> ); }; const ChildrenComponent =({ userName }) => { console.log("rendered", userName); return <div> {userName} </div>; };
Дочерний компонент должен отображаться только один раз, так как значение count не имеет к нему никакого отношения. И тем не менее он рендерится при каждом нажатии на кнопку.
https://miro.medium.com/max/700/1*UC19Qvfj06VAy63lR8mOFg.png
Отредактируем немного ChildrenComponent:
ChildrenComponent
import React ,{useState} from "react"; const ChildrenComponent = React.memo(({userName}) => { console.log('rendered') return <div> {userName}</div> })
Теперь не имеет значения, сколько раз пользователь кликнет на кнопку, компонент отрендерится только при необходимости.
Организовать CSS сложнее, чем JavaScript, но можно постараться.
// CSS файл .body { height: 10px; } // JSX return <div className='body'> </div>
const bodyStyle = { height: "10px" } return <div style={bodyStyle}> </div>
Одна из новейших возможностей JS сделает ваш код более читаемым.
return ( <> <div> {user.name} </div> <div> {user.age} </div> <div> {user.profession} </div> </> )
const { name, age, profession } = user; return ( <> <div> {name} </div> <div> {age} </div> <div> {profession} </div> </> )
Передать строковые данные проще, чем вы думаете.
return( <Navbar title={"My Special App"} /> )
return( <Navbar title="My Special App" /> )
Уберите весь код JavaScript из JSX-разметки, если он не служит какой-либо цели рендеринга или функциональности UI.
return ( <ul> {posts.map((post) => ( <li onClick={event => { console.log(event.target, 'clicked!'); // <- THIS IS BAD }} key={post.id}>{post.title} </li> ))} </ul> );
const onClickHandler = (event) => { console.log(event.target, 'clicked!'); } return ( <ul> {posts.map((post) => ( <li onClick={onClickHandler} key={post.id}> {post.title} </li> ))} </ul> );
Используйте строковые литералы вместо громоздкой конкатенации строк.
const userDetails = user.name + "'s profession is" + user.proffession return ( <div> {userDetails} </div> )
const userDetails = `${user.name}'s profession is ${user.proffession}` return ( <div> {userDetails} </div> )
Старайтесь импортировать модули в определенном порядке, чтобы сделать код более логичным.
import React from 'react'; import ErrorImg from '../../assets/images/error.png'; import styled from 'styled-components/native'; import colors from '../../styles/colors'; import { PropTypes } from 'prop-types';
Эмпирическое правило заключается в следующем порядке импорта:
import React from 'react'; import { PropTypes } from 'prop-types'; import styled from 'styled-components/native'; import ErrorImg from '../../assets/images/error.png'; import colors from '../../styles/colors';
Неявный возврат делает ваши функции изящнее. Но не злоупотребляйте этой фичей, она уместна только в простых функциях.
const add = (a, b) => { return a + b; }
const add = (a, b) => a + b;
Всегда используйте PascalCase для имен компонентов и camelCase – для экземпляров.
import reservationCard from './ReservationCard'; const ReservationItem = <ReservationCard />;
import ReservationCard from './ReservationCard'; const reservationItem = <ReservationCard />;
Не используйте зарезервированные имена атрибутов для передачи пропсов, другие разработчики могут быть к этому не готовы.
<MyComponent style="dark" /> <MyComponent className="dark" />
<MyComponent variant="fancy" />
Используйте двойные кавычки для атрибутов JSX и одинарные – для всего остального кода JavaScript.
<Foo bar='bar' /> <Foo style={{ left: "20px" }} />
<Foo bar="bar" /> <Foo style={{ left: '20px' }} />
Всегда используйте camelCase для имен пропсов или PascalCase, если значение атрибута – это другой React-компонент.
<Component UserName="hello" phone_number={12345678} />
<MyComponent userName="hello" phoneNumber={12345678} Component={SomeComponent} />
Если ваш компонент занимает больше, чем одну строчку, всегда оборачивайте его в скобки.
return <MyComponent variant="long"> <MyChild /> </MyComponent>;
return ( <MyComponent variant="long"> <MyChild /> </MyComponent> );
Если у вашего компонента нет дочерних элементов, используйте самозакрывающийся тег для улучшения читаемости.
<SomeComponent variant="stuff"></SomeComponent>
<SomeComponent variant="stuff" />
Не используйте подчеркивание в любых внутренних методах.
const _onClickHandler = () => { // do stuff }
const onClickHandler = () => { // do stuff }
Всегда устанавливайте атрибут alt для теги img и не используйте в нем слова image и picture. Альтернативный текст предназначен для скринридеров, которые и так объявляют элемент как изображение, зачем повторяться?
<img src="hello.jpg" /> <img src="hello.jpg" alt="Picture of me rowing a boat" />
<img src="hello.jpg" alt="Me waving hello" />
Вот и все. Поздравляем, если вы зашли так далеко! Надеюсь, вы кое-что узнали из этой статьи.
Ваш адрес email не будет опубликован. Обязательные поля помечены *
Сохранить моё имя, email и адрес сайта в этом браузере для последующих моих комментариев.
Δ
Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.