Дополнительно
Можете получить доступ к экземпляру реагировать (это) внутри обработчика событий
Я пишу простой компонент в ЕС6 (с BabelJS), и функций этого.выполнении функция setState не работает.
Типичные ошибки включают что-то вроде
не удается прочитать свойство 'выполнении функция setState' не определено
или
это.выполнении функция setState не функция
Вы знаете, почему? Вот код:
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
}
sendContent(e) {
console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
}
changeContent(e) {
this.setState({inputContent: e.target.value})
}
render() {
return (
<div>
<h4>The input form is here:</h4>
Title:
<input type="text" ref="someref" value={this.inputContent}
onChange={this.changeContent} />
<button onClick={this.sendContent}>Submit</button>
</div>
)
}
}
export default SomeClass
201
19
в
этот.changeContent должен быть привязан к экземпляру компонента через это.changeContent.привязать(это)
прежде, чем быть переданным какonChange, после
проп, в противном случае " это " переменная в теле функции не ссылается на экземпляр компонента, а дляокна
. См Function::bind.При использовании `реагировать.createClass вместо занятий на ES6, каждый жизненный цикл метода, определенного компонента будет автоматически привязан к экземпляру компонента. См Autobinding.
Помните, что привязка функция создает новую функцию. Вы можете либо связать его непосредственно в визуализации, что означает, что новая функция будет создаваться каждый раз, когда компонент оказывает, или связать его в свой конструктор, который будет только огонь один раз.
против
Ссылки на экземпляр компонента и не реагировать.судей: вам нужно изменить
реагировать.рефов.someref до этого.рефов.someref
. Вы'll тоже нужно связатьsendContent
метод экземпляра компонента, так что " это " относится к нему.Morhaus правильно, но это может быть решена без
привязки
.Вы можете использовать функция стрелка вместе с свойства класса предложение:
Поскольку функция стрелка объявлена в области конструктора, а потому, что стрелочные функции поддерживать " это " от их декларирования объема, все это работает. Недостатком здесь является то, что не будет функции на прототипе, все они будут воссозданы с каждым компонентом. Однако, это вовсе'т много недостатка, так как "привязка" результатов, в то же самое.
Этот вопрос является одним из первых вещей, которые большинство из нас испытывают, при переходе от
реагировать.компонент синтаксис определения createClass()
в классе ЕС6 способом продленияреагировать.Компонент
. Это вызвано " это " контекст различий в реакции.createClass()против
расширяет реагировать.Компонент`. ИспользуяРеагировать.createClass()
будет автоматически привязанправильно
контекст (значений), но это не тот случай, когда использование классов ЕС6. Когда делаешь это на ES6 способом (путем расширенияреагировать.Компонент
) вэтой
связинулевой
по умолчанию. Свойства класса автоматически не привязать к классу реагируют (компонент) экземпляра.Подходы, чтобы решить этот вопрос
Я знаю всего 4 общие подходы.
@autobind
прежде чем методы привязкиэто
правильную ссылку к компоненту'ы контексте. импорт autobind с 'autobind-декоратор'; класса SomeClass расширяет реагировать.Компонент { @autobind handleClick() { консоль.журнал(этот); // экземпляр компонента реагируют } рендер() { возвращение ( <кнопка функция onclick={этот.handleClick}>< кнопка/> ); } } Autobind декоратор достаточно умен, чтобы позволить нам привязать все методы внутри класса компонента сразу, как подход #1.Класс Autobind Еще один НПМ пакет, который широко использован для того чтобы решить эту проблему связывания. В отличие от Autobind декоратора, она не использует декоратор шаблон, но очень просто использует функцию внутри конструктора, который автоматически привязывает компонент'ы методы правильного ведения
это
. импорт autobind с 'класс-autobind'; класса SomeClass расширяет реагировать.Компонент { конструктор() { autobind(это); // или если вы хотите связать только лишь выбрать функции: // autobind(это, 'handleClick'); } handleClick() { консоль.журнал(этот); // экземпляр компонента реагируют } рендер() { возвращение ( <кнопка функция onclick={этот.handleClick}>< кнопка/> ); } } PS: Другие очень похожие библиотеки Autobind реагировать.Рекомендации
Если бы я был тобой, я бы придерживаться подхода #1. Однако, как только вы получаете тонну связывает в конструкторе класса, я бы порекомендовал вам изучить один из вспомогательных библиотек, упомянутых в подход #4.
Другие
Это's не относящиеся к данному вопросу у вас нет, но вы должны'т злоупотребляйте ссылки]5.
Хотя предыдущие ответы дали обзор основных решений (т. е. привязка, стрелка функций, декораторов, которые сделают это для вас), я'вэ еще, чтобы встретить ответ, который на самом деле объясняет, почему это надо—что на мой взгляд является корнем путаницу и приводит к ненужным действия, такие как ненужные привязки и не надо слепо копировать то, что делают другие.
это
является динамическимЧтобы разобраться в этой конкретной ситуации, кратко остановимся на том, как " это " работает. Ключевым моментом здесь является то, что " это " является время выполнения обязательной и зависит от текущего контекста выполнения. Следовательно, почему. он'ы часто упоминается как "контекст" по—дает информацию о текущем контексте выполнения, а почему нужно привязываться, потому что вы свободные "в контексте" и Но позвольте мне проиллюстрировать этот вопрос с фрагмент:
В этом примере мы получаем
3
, как ожидалось. Но посмотрите на этот пример:Это может быть неожиданным, чтобы найти, что он регистрирует не определено—откуда у
3
идти? Ответ кроется в "в контексте", У, или как вы выполнить функция. Сравните, как мы называем функции:Обратите внимание на разницу. В первом примере мы указываем, где именно
бар
метод<суп>1</с SUP>, который расположен—напрограммой
объект:Но во втором, мы храним метод в переменной и использовать эту переменную для вызова метода, без явного указания где этот метод существует на самом деле, теряя связи:
В этом и заключается проблема, когда вы храните способ в переменной, оригинальной информации о том, где этот метод находится (контекст, в котором способ выполняется), теряется. Без этой информации, во время выполнения, нет никакого способа для интерпретатора JavaScript, чтобы связать правильный " это "—без конкретного контекста, " это " не работает, как ожидалось в<SUP-серфинг и GT;2</суп>.
Касающиеся реагировать
Здесь'с примером компонента реагируют (сокращенное для краткости), страдающих от этой проблемы:
Но почему, и как в предыдущем разделе, относятся к этому? Это потому, что они страдают от абстракцию с той же проблемой. Если вы посмотрите как реагируют ручками handlers событие](https://github.com/facebook/react/blob/64e1921aab4f7ad7e2f345f392033ffe724e52e9/packages/events/EventPluginHub.js#L148):
Поэтому, когда вы делаете
функция onclick={этот.handleClick}
, методэто.handleClick
в конечном итоге присвоено переменнойслушатель
<суп>3</суп>. Но теперь вы видите, возникнуть—поскольку проблема мы'вэ назначается это.handleClickв
слушатель, мы уже не уточнил, где именно
handleClickидет от! От реагировать'с точки зрения,
слушатель- это лишь некоторые функции, не привязан к какому-либо объекту (или в данном случае, экземпляр компонента реагируют). Мы потеряли контекст и, таким образом, переводчик не может определить это значение, чтобы использовать **внутри**
handleClick`.Почему привязка работает
Вам может быть интересно, если переводчик решает " это " значения во время выполнения, поэтому я могу привязать обработчик так, что она работает? Это потому, что вы можете использовать функцию
#привязать
к гарантии это значение во время выполнения. Это делается путем установки внутренней " это "обязательный свойство функции, позволяя ему не сделаете "это":Когда эта строка выполняется, предположительно в конструкторе, текущей " это "попадает в плен (экземпляра компонента реагируют) и установить в качестве внутренней" это " привязка совершенно новые функции, возвращаемые из функции#персонализация`. Это гарантирует, что когда " это "вычисляется во время выполнения, переводчик не пытайтесь что-либо вывести, но использовать предоставленные" это " значение, которое вы дали ему.
Почему свойства функции стрелка работать
В настоящее время функционируют стрелки свойств внеурочной работе Бабеля на основе transpilation:
Становится:
И это работает за счет того, функции стрелка не **** не связывать свои, но брать " это " в их видимости. В данном случае,
конструктор
'ыэто
, которое указывает на экземпляр—таким образом, компонент реагировать, давая вам правильныйэто
.<суп>4</SUP и ГТ;<суп>1</с SUP> Я вставлять "метод", чтобы обратиться к функции, которая должна быть привязана к объекту, и "функция" и для тех, кто не. в <SUP-серфинг и GT;2</суп> во втором фрагменте, не определено регистрируется вместо 3, потому что " это " по умолчанию глобальный контекст исполнения ("окно", когда не в строгом режиме, иначе
неопределенное
), когда оно не может быть определено с помощью определенного контекста. И в Примере окно.фу не существует, таким образом, определено. <суп>3</суп> если вы идете вниз по кроличьей норе, как события в очереди событий выполняются, [
invokeGuardedCallback](https://github.com/facebook/react/blob/64e1921aab4f7ad7e2f345f392033ffe724e52e9/packages/shared/invokeGuardedCallback.js#L27) называется на слушателя. <суп>4</с SUP> Это'ы на самом деле *сложнее*. Реагировать внутренне пытается использовать
#функция распространяется на слушателей для собственного использования, но это не работает стрелочные функции, как они просто не связывают "это". Это означает, что, когдаэто
внутри функции стрелка реально оценивали, что " это " будет решен каждую лексическую среду каждого контекста выполнения текущего кода модуля. Контекст выполнения, который окончательно разрешает иметь " это "привязка это конструктор, который имеет" это " указывает на текущий экземпляр компонента реакции, что позволяет ему работать.Моя рекомендация использовать стрелочные функции как свойства
и не используйте стрелочные функции, как
потому что второй подход будет генерировать новую функцию каждый предоставляете вызов на самом деле это означает, что новый указатель на новую версию реквизит, чем если вы потом будете заботитесь о производительности, вы можете использовать реагировать.PureComponent или в реагировать.Компонент вы можете переопределить shouldComponentUpdate(nextProps, nextState) и мелкие проверки, когда реквизит прибыл
Нам нужно связать функцию событие с компонентом в конструктор следующим образом:
Спасибо
Мы должны связывать наши функции с
этим
, чтобы получить экземпляр функции в классе. Так как в ПримереТаким образом это.государство будет действительный объект.
Вы можете решить эту проблему выполните следующие действия
Изменение функции sendContent с
Изменение функции render с
Вы можете решить эту тремя способами
1.Привязать функцию в конструктор следующим образом
2.Привязать, когда он вызывается
3.By с помощью функции стрелка
привязать(это)
может исправить эту проблему, и теперь мы можем использовать еще 2 способа достичь этого, если вы не'т, как с помощью
связывать` .`
класс приложение app1 расширяет реагировать.Компонент { конструктор(реквизит) { супер(реквизит); // Если закомментировать следующую строку // мы получим ошибку времени выполнения, что эта
неопределено. это.changeColor = это.changeColor.привязать(это); }changeColor(е) { е.currentTarget.стиль.свойство backgroundColor = " и#00FF00 и"; консоль.журнал(это.реквизит); }
рендер() { возвращение ( <див> <кнопка функция onclick={этот.changeColor}> кнопка< кнопка/> </див> ); } } ``
Если мы определяем функцию как атрибут или поле класса с функцией стрелка, мы не'т должны использовать
привязать(это)
больше.класс приложения app2 расширяет реагировать.Компонент { changeColor = е => { е.currentTarget.стиль.свойство backgroundColor = " и#00FF00 и"; консоль.журнал(это.реквизит); }; рендер() { возвращение ( <див> <кнопка функция onclick={этот.changeColor}> кнопка 1< кнопка/> </див> ); } }
Если мы используем функцию стрелки, как JSX обратного вызова, мы не'т должны использовать
привязать(это)
либо. И более того, мы можем передать параметры. Выглядит хорошо, разве'т его? но ее недостатком является производительность концерна, для деталей, пожалуйста, обратитесь ReactJS укор.App3 класс расширяет реагировать.Компонент { changeColor(е colorHex) { е.currentTarget.стиль.свойство backgroundColor = colorHex; консоль.журнал(это.реквизит); } рендер() { возвращение ( <див> <кнопка функция onclick={е => это.changeColor(е " и#число ff0000", у)}> кнопка 1< кнопка/> </див> ); } }
И я создал сайт CodePen для демонстрации этих фрагментов кода, надеюсь, что это помогает.
если кто-нибудь достигнет этого ответа, вот способ, чтобы связать все функции без необходимости привязывать их вручную
в конструкторе():
или создать эту функцию в глобальном.файл jsx
и в конструкторе() вызывать его так:
Эта проблема происходит, потому что это.changeContent " и " функция onclick={этот.sendContent} не привязан этот экземпляра компонента .
Есть и другое решение (помимо использовать привязку() в конструкторе() ) использовать стрелку функций из ES6, которые разделяют ту же лексическую область видимости окружающего кода и сохранить это , так что вы можете изменить ваш код в Render() Для будет :
Привет, если вы хотите не заботятся о привязке вашего вызова функции. Вы можете использовать 'класс-autobind' и импортировать его, как это
Не пишите autobind до супер вызов, потому что он не будет работать
В случае, если вы хотите сохранить привязку в синтаксисе конструктора, вы можете использовать предложение привязать оператора и преобразовать ваш код, как следовать :
Вместо :
намного проще, не нужно
привязать(это)
илиfatArrow
.эта проблема случается после react15.0 ,что обработчик события не'т авто привязать к компоненту. таким образом, вы должны связать этот компонент вручную всякий раз, когда обработчик событий будет вызываться.
есть несколько способов решить проблему. но вы должны знать, какой метод лучше и почему? В общем, мы рекомендуем обязательный свои функции в конструкторе класса или использовать функцию стрелки.
эти два метода не создает новую функцию, когда компонент, делают каждый раз. поэтому наши ChildComponent не будет повторно из новый реквизит изменения функции, или может вызвать проблемы с производительностью.
Вы используете ES6 в такой функции не будет привязки к "эта" в контексте автоматически. Вам придется вручную привязать функции к контексту.
Ваши функции должен обязательными для того, чтобы играть с государством или реквизит в обработчиках событий
В ES5, привязать обработчик события работает только в конструкторе, но Дон'т связываться непосредственно на рендере. Если вы делаете привязку непосредственно в рендер, то он создает новую функцию каждый раз, когда ваш компонент оказывает и повторное отображение. Так что вы всегда должны привязать его в конструктор
В ЕС6, используйте кнопки со стрелками
При использовании функции стрелка, то вам не нужно делать обязательным и вы можете также держаться подальше от сферы вопросы, связанные с
Александр Kirszenberg правильно, но еще важно обратить внимание на то , где вы положили ваши привязки. Я застрял с ситуацией за дней(наверное, потому что я'м новичок), но в отличие от других, я знал о bind(куда я обращался уже) так что я просто не могла'т получить мою голову вокруг, почему я по-прежнему возникают эти ошибки. Получается, что я имел привязку в неправильном порядке.
Другой также возможно и то, что я назвал функцию в "эта.государство", который не был осведомлен о привязать, потому что он оказался выше линии привязки,
Ниже то, что я имел(кстати это мой первый блог, но я думал, что это было очень важно, так как я не мог'т найти решение где-либо еще):
Решение:
`` импорт реагируют с 'реагировать'
класса SomeClass расширяет реагировать.Компонент { конструктор(реквизит) { супер(реквизит) это.состояние = { inputContent: 'типом startvalue' } }
sendContent = (е) => { консоль.журнал('отправив ввод контента ' это.государства.inputContent); }
changeContent = (е) => { это.выполнении функция setState({inputContent: электронная.цель.значение},()=>{ консоль.журнал('государство:' это.государства); }) }
рендер() { возвращение ( <див> <Н4>форма ввода-это здесь:</Н4> Название: в <тип входного=на"текст" и значение={этот.государства.inputContent} onChange, после={этот.changeContent} /> <кнопка функция onclick={этот.sendContent}>отправить< кнопка/> </див> ) } }
экспорт SomeClass по умолчанию
``
Привязать свои функции в конструкторе класса.
Привязка ваших функций в JSX побега шаблон подтяжки {} {этот.имя_метода.привязать(это)}