Відповіді на запитання по React

Тут ти знайдеш відповіді на питання, які часто зустрічаються на співбесідах

Часто зустрічається проблема, коли виникає помилка в якійсь модалці або формі, в результаті ми отримуємо білий екран і додаток, що повністю не працює. Логічним виходом із цієї ситуації є обробка помилок у окремих незалежних частинах додатку, щоб виниклі у них помилки оброблялися і впливали на працездатність усього додатку. Саме для цього і створено компоненти Error Boundaries.
Ця функціональність добре і коротко описана в офіційній документації.
Наочний приклад.
Також є бібліотеки, які пропонують готову реалізацію Error Boundaries.

Якщо ти виводиш у своєму додатку якийсь список чи масив, тобі потрібно додати кожному елементу аттрибут key. Найчастіше використовується id об'єкта у масиві, це гарантує його унікальність.

Ключі потрібні щоб React міг точно визначити місце елемента у списку з часом. Тобто якщо ти не вкажеш ключі для елементів списку і додаси на початок або середину списку якийсь елемент, алгоритм порівняння React може заплутатися і відображати твій список не коректно.

Не керовані компоненти дуже схожі на звичайні html форми. Вони зберігають дані в собі які можно витягувати з них за допомогою refів. Валідацію можна проводити після відправлення форми. Не керовані компонети можна використовувати для дуже простих форм, коли не потрібна якась логіка при роботі з формою.

Керовані компоненти приймають пропси в якості початкового значення і зберігають дані в стейті компонента або в якомусь іншому стейті, наприклад, Redux. У керованих форм є кілька явних переваг:

  • завжди є доступ до валідації полів
  • можна робити не активною кнопку відправки доки всі поля не заповнені коректними даними
  • форматування даних у полях, наприклад кредитні картки та номери телефонів
//non-managed component class Form extends Component { handleSubmitClick = () => { const name = this._name.value; //do something with "name" } render(){ return( <div> <input type="text" ref={input => this._name = input} /> <button onClick={this.handleSubmitClick}>Sign Up</button> </div> ) } } //managed component class Form extends Component { constructor(){ super(); this.state = { name: "" } } handleNameChange = (event) => { this.setState({name: event.target.value}); } render(){ return(){ <div> <input type="text" value={this.state.name} onChange={this.handleNameChange} /> </div> } } }

constructor - запускається при виклику компонента і використовується для ініціалізації
componentDidMount - запускається після того як компонент відрендерився
componentDidUpdate - викликається коли компонент перерендерився
componentWillUnmount - запускається перед тим як компонент буде демонтований
shouldComponentUpdate - компоненти перемальовуються завжди коли змінюється стейт або коли компонент отримує нові пропси. Якщо компонент великий і рендер займає багато ресурсів і часу ти можеш заборонити ререндерувати компонент. componentDidCatch - дозволяє перехоплювати помилки, що відбулися в дочірніх компонентах

Обгортуючи код у <div> ви створюєте додатковий вузол у DOM дереві.
Фрагмент <></> не створює вузлів.
Також в деяких випадках обертання в <div> не зручне, приклад у коді:

class Table extends React.Component { render() { return ( <table> <tr> <Columns /> </tr> </table> ); } } class Columns extends React.Component { render() { return ( <div> <td>Привет</td> <td>Мир</td> </div> ); } } //Result <table> <tr> <div> <td>Привет</td> <td>Мир</td> </div> </tr> </table> //Using a fragment will not add div to the table structure

JSX це розширення JavaScript. Можна сказати, що це суміш HTML розмітки з JS функціональністю. JSX використовується для створення компонентів React. Ти можеш створити розмітку та одразу ж описати логіку компонента.
JSX компілюється у функції React.createElement() за допомогою Babel.

function getGreeting(user) { if (user) { return <h1>Hi, {formatName(user)}!</h1>; } return <h1>Hello Stranger!</h1>; }

Портал це компонент, який рендерить свій вміст у DOM вузол, поза DOM-ієрархією батьківського компонента.

Портали застосовують у ситуаціях, коли потрібно, щоб дочірні компоненти візуально виривалися з батьківського контейнера. Типові приклади використання порталів:

  • Модальні діалогові вікна
  • Спливаючі підказки
  • Завантажувачі
<html> <body> <div id="app-root"></div> <div id="modal-root"></div> </body> </html> ///////////////////////////////////// //below is the whole code from app-root component const appRoot = document.getElementById('app-root'); const modalRoot = document.getElementById('modal-root'); ... //we can render modal in modal-root from app-root function MyModal() { return ReactDOM.createPortal( <div className="modal"> <p>This is part of the modal</p> </div>, modalRoot ); }

Refи дають можливість прямого доступу до DOM-вузлів.

Філософія React не рекомендує використовувати рефи.

Але є деякі випадки, коли на це можна піти:

  • керування фокусом, виділення тексту або робота з медіа
  • робота з анімаціями
  • робота зі сторонніми DOM-бібліотеками
function CustomTextInput(props){ let textInput = React.createRef(); function handleClick(){ textInput.current.focus(); } return( <div> <input type="text" ref={textInput} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); }

Комонент вищого порядку - це функція, яка приймає компонент і повертає новий компонент з додатковою функціональністю.

HOC це патерн, заснований на композиції.

HOC зручно використовувати, коли потрібно додати однакову функціональність для різних компонентів.

function logProps(WrappedComponent){ return class extends React.Component { componentDidUpdate(prevProps){ console.log('Previous props: ', prev.props); console.log('Current props: ', this.props); } render() { return <WrappedComponent {...this.props} />; } } } // LogedComponent is TestComponent component // which logs props when updating const LogedComponent = logProps(TestComponent)

Хуки – це функції, за допомогою яких ти можеш контролювати стан та життєвий цикл у функціональних компонентах. Хуки не працюють усередині класів – вони дають тобі можливість використовувати React без класів. Список хуків з коротким описом:

useState - дозволяє створювати стейт у функціональних компонентах та керувати ним

useContext - цей хук дозволяє використовувати контекст у функціональних компонентах, тобто передавати значення від батька до дочірніх компонентів минаючи проміжні

useEffect та useLayoutEffect - дозволяють реалізувати роботу трьох методів життєвого циклу – componentDidMount, componentDidUpdate, componentWillUnmount у функціональних компонентах

useRef – дозволяє звертатися до елементів DOM дерева на пряму

useReducer - дозволяє виносити дані з компонента до глобального стейту, емітуючи роботу Redux з коробки

useMemo, useCallback - дозволяють оптимізувати обчислення та ререндеринг у компонентах

Також ти можеш створювати свої хуки та використовувати їх у будь-яких компонентах.

State це об'єкт, який зберігає динамічні дані компонента і дозволяє компоненту відстежувати зміни між рендерами. Документація

Пропси
Класові - пропси потрапляють у конструктор класу і доступ до них можливий через this.props
Функціональні - пропси приймаються функцією як єдиний агрумент, так що доступ до них можливий просто через props

Стейт
Класові - в конструкторі класу можна задати початковий стан компонета. Доспут до стейту здійснюється через this.state. А змінювати його можна за допомогою this.setState() Функціональні - можна змінювати стан за допомогою хука useState

Методи життєвого циклу
Класові - за допомогою методів життєвого циклу ти можеш контролювати стан компонента в різних стадіях і виконувати необхідний у тому чи іншому випадку код.
Функціональні - у функціональних компонентах методів життєвого циклу немає, але є хук useEffect який поєднує в собі componentDidMount(), componentDidUpdate() і componentWillUnmount()

Babel це транспайлер котрий перекладає сучасний JS у більш старий до ES6.
Також babel може переводити JSX в код, який здатний відтворити браузер.

Context API дозволяє прокидати пропси крізь вкладеність компонентів. Використовуючи контекст, тобі не потрібно буде прокидати якийсь пропс углиб дерева компонентів. Для цього потрібно оголосити пропси в компоненті провайдера і ти зможеш отримати ці пропси в будь-якому дочірньому компоненті. Це дозволяє полегшити роботу з компонентами та зменшує кількість помилок.

Пропси це дані які передаються у компонент з батьківського компонента.

Пропси не можна змінювати, вони призначені лише для читання.

Також ти можеш отримати доступ до контенту що розташовується між відкриваючим та закриваючим компонентами теги за допомогою props.children
props.children зручно використовувати для композиції компонентів.

PureComponent це той же React.Component тільки з однією особливістю. Звичайні реакт компоненти ререндеряться щоразу, коли змінюються пропси або стейт. У деяких випадках нам не потрібно цього робити, і тут нам на допомогу приходить метод *shouldComponentUpdate.*
У ньому ми можемо задати умови, чи буде компонент перемальовуватися чи ні.
У PureComponent цей метод працює з коробки.
Він проводить поверхневе порівняння поточних стейтів і пропсів з новими. Через поверхневе порівняння з PureComponent потрібно бути обережнішим. Якщо ти змінюватимеш дані на пряму, компонент може не перемальовуватися навіть коли це буде потрібно. Тут необхідно дотримуватися іммутабельності даних, добре підходять для цього: спред оператор, map, filter і reduce.

React Reconciliation це алгоритм порівняння, за допомогою якого React розуміє які елементи на сторінці потрібно перемальовувати.

Для цього створюється віртуальне дерево DOM. Воно відповідає реальному DOM дереву сторінки, представляючи його легковажну об'єктну версію. Коли під час роботи програми змінюється стан того чи іншого компонента, React вносить зміни у віртуальне DOM дерево і порівнює його з реальним деревом елементів сторінки.

Процес порівняння (Reconciliation) походить від батьківського компонента до дочірніх. Коли він знаходить відмінності, компоненти не збігаються або мають різні атрибути, React перерендерує не відповідний компонент у реальному DOM.

Цей алгоритм дозволяє швидко знаходити елементи, які потрібно перемалювати, а також перемальовувати тільки ті елементи, які необхідно.

Розглянемо пару прикладів. Якщо ти вніс зміни до першого елемента списку, React перемальовує лише його, а не весь список.
Або якщо ти змінив стейт у кореневому компоненті, React перемалює тільки ті дочірні компоненти, які використовують змінене значення, а не весь UI.
Так як перемальовка UI є дуже ресурсомістким процесом, використання віртуального DOM робить React застосунки такими спритними.

Інші питання

Якщо у тебе є питання чи пропозиції, напиши мені: Telegram | LinkedIn
© 2023 All rights reserved