Шаблони зв’язування реакцій: 5 підходів до роботи з цим

Така поведінка JavaScript у ключових словах незрозуміло розробників протягом багатьох століть.

Існує щонайменше п’ять способів обробки цього контексту в React. Давайте розглянемо достоїнства кожного підходу.

1. Використовуйте React.createClass

Якщо ви використовуєте React.createClass, React автоматично прив'язує до цього всі функції . Отже, це ключове слово автоматично прив’язується до екземпляра вашого компонента:

// This magically works with React.createClass// because `this` is bound for you.onChange={this.handleChange}

Однак із появою класів ES6 цей нестандартний підхід до створення класів не є майбутнім React. Насправді createClass, швидше за все, буде витягнуто з ядра React у наступному випуску.

2. Прив’язка у візуалізації

Решта цих підходів передбачає, що ви оголошуєте компоненти React за допомогою класів ES6. Якщо ви використовуєте клас ES6, React більше не вводить автоматично. Одним із способів вирішити цю проблему є виклик bind у рендерінгу:

onChange={this.handleChange.bind(this)}

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

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

3. Використовуйте функцію стрілки у візуалізації

Цей підхід схожий на №2. Ви можете уникнути зміни цього контексту, використовуючи функцію стрілки в рендері:

onChange={e => this.handleChange(e)}

Цей підхід має такий самий потенційний вплив на ефективність, як №2.

Варто розглянути альтернативні підходи нижче, оскільки вони пропонують чудову продуктивність за невеликих додаткових витрат.

4. Прив'язка в конструкторі

Одним із способів уникнути прив'язки в рендерінгу є прив'язка до конструктора (інший підхід обговорюється в №5 нижче).

constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); }

Цей підхід на даний час рекомендується у документах React для «кращої роботи у вашому додатку». Це також підхід, який я використовую в «Створення додатків за допомогою React та Redux в ES6» на Pluralsight.

Однак у більшості програм наслідки підходу №2 та №3 не будуть помітні, тому переваги підходу №2 та №3 щодо читабельності та технічного обслуговування можуть переважити проблеми, пов’язані з продуктивністю у багатьох додатках.

Але якщо ви готові використовувати функції етапу 2, остаточний варіант нижче, швидше за все, найкращий вибір.

5. Використовуйте функцію стрілки у властивості класу

Цей прийом спирається на запропоновану властивість властивості класу. Щоб скористатися цим підходом, потрібно ввімкнути-клас-властивості або активувати етап-2 у Babel.

handleChange = () => { // call this function from render // and this.whatever in here works fine. };

Цей підхід має безліч переваг:

  1. Функції зі стрілками приймають це прив'язування області, що охоплює (іншими словами, вони не змінюють значення цього), тому все працює автоматично.
  2. Це дозволяє уникнути проблем продуктивності підходів №2 та №3.
  3. Це дозволяє уникнути повторень у підході No4.
  4. Переформатувати зі стилю ES5 createClass у цей стиль просто, перетворивши відповідні функції у функції стрілок. Насправді існує повністю автоматизований спосіб вирішити це за допомогою кодемоду.

Резюме

Ця блок-схема, яка підсумовує рішення.

Ось повні робочі приклади всіх 5 підходів:

// Approach 1: Use React.createClass var HelloWorld = React.createClass({ getInitialState() { return { message: 'Hi' }; }, logMessage() { // this magically works because React.createClass autobinds. console.log(this.state.message); }, render() { return (  ); } }); // Approach 2: Bind in Render class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; } logMessage() { // This works because of the bind in render below. console.log(this.state.message); } render() { return (  ); } } // Approach 3: Use Arrow Function in Render class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; } logMessage() { // This works because of the arrow function in render below. console.log(this.state.message); } render() { return (  this.logMessage()} /> ); } } // Approach 4: Bind in Constructor class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; this.logMessage = this.logMessage.bind(this); } logMessage() { // This works because of the bind in the constructor above. console.log(this.state.message); } render() { return (  ); } } // Approach 5: Arrow Function in Class Property class HelloWorld extends React.Component { // Note that state is a property, // so no constructor is needed in this case. state = { message: 'Hi' }; logMessage = () => { // This works because arrow funcs adopt the this binding of the enclosing scope. console.log(this.state.message); }; render() { return (  ); } }

То що люди віддають перевагу? Опитування:

Як ви обробляєте прив'язку в #reactjs сьогодні?

Приклади: //t.co/z7OKxe39VA

- Корі Хаус (@housecor) 18 серпня 2016 р

Є інші способи вирішити це? Будь ласка, повідомте коментарі.

Величезне спасибі @dan_abramov, @kentcdodds та @dmosher за їх цінні вклади та відгуки!

Кори Хаус є автором "Створення додатків за допомогою React і Redux в ES6", "Створення додатків за допомогою React і Flux", "Чистий код: Написання коду для людей" та багатьох інших курсів з Pluralsight. Він є архітектором програмного забезпечення у VinSolutions, Microsoft MVP, і навчає розробників програмного забезпечення на міжнародному рівні таким практикам, як розробка інтерфейсу та чисте кодування.