2015-11-28 4 views
51
class PlayerControls extends React.Component { 
    constructor(props) { 
    super(props) 

    this.state = { 
     loopActive: false, 
     shuffleActive: false, 
    } 
    } 

    render() { 
    var shuffleClassName = this.state.toggleActive ? "player-control-icon active" : "player-control-icon" 

    return (
     <div className="player-controls"> 
     <FontAwesome 
      className="player-control-icon" 
      name='refresh' 
      onClick={this.onToggleLoop} 
      spin={this.state.loopActive} 
     /> 
     <FontAwesome 
      className={shuffleClassName} 
      name='random' 
      onClick={this.onToggleShuffle} 
     /> 
     </div> 
    ); 
    } 

    onToggleLoop(event) { 
    // "this is undefined??" <--- here 
    this.setState({loopActive: !this.state.loopActive}) 
    this.props.onToggleLoop() 
    } 

Я хочу обновить loopActive состояние на тумблер, но this объект не определен в обработчике. Согласно учебному документу, I this должен ссылаться на компонент. Я что-то упускаю?React: «это» не определено внутри компонента функции

ответ

72

ES6 React.Component не автоматически связывает методы с самим собой. Вы должны связать их самостоятельно в конструкторе. Как это:

constructor (props){ 
    super(props); 

    this.state = { 
     loopActive: false, 
     shuffleActive: false, 
    }; 

    this.onToggleLoop = this.onToggLoop.bind(this); 

} 
+4

, если вы измените свойство onClick на '() => this.onToggleLoop' после перемещения функции onToggleLoop в ваш класс реагирования, он также будет работать. – Sam

+18

Вам действительно нужно привязывать каждый метод каждого класса реагирования? Разве это не сумасшедший? –

+2

@AlexL Есть способы сделать это без явной привязки методов. если вы используете babel, можно объявить каждый метод для компонента React как функции стрелок. Здесь есть примеры: https://babeljs.io/blog/2015/06/07/react-on-es6-plus – Ivan

37

Существует несколько способов.

Одним из них является добавление this.onToggleLoop = this.onToggleLoop.bind(this); в конструктор.

Другие функции стрелок onToggleLoop = (event) => {...}.

А затем есть onClick={this.onToggleLoop.bind(this)}.

+0

@limelights для редактирования. –

+0

Nice и ясно. – Ionut

+0

Почему работает onToogleLoop =() => {}? У меня такая же проблема, и я привязывал ее к моему конструктору, но он не работал ... и теперь я видел ваше сообщение и заменяю свой метод синтаксисом функции стрелки, и он работает.Вы можете мне это объяснить? – DrMed

7

я столкнулся с подобной привязки в функции визуализации и в конечном итоге передавая контекст this следующим образом:

{someList.map(function(listItem) { 
    // your code 
}, this)} 

Я также использовал:

{someList.map((listItem, index) => 
    <div onClick={this.someFunction.bind(this, listItem)} /> 
)} 
+0

Это много ненужных функций, которые вы создаете там, каждый раз список визуализируется ... –

+0

@TJCrowder Да, это правда, эти функции создаются заново каждый раз, когда вызывается рендеринг. Лучше создавать функции как методы класса и связывать их один раз с классом, но для новичков привязка к контексту вручную может быть полезным – duhaime

0

Если вы вызываете свой созданный метод в методы жизненного цикла, такие как componentDidMount ... тогда вы можете использовать только this.onToggleLoop = this.onToogleLoop.bind(this) и функция стрелки жира onToggleLoop = (event) => {...}.

Обычный подход к объявлению функции в конструкторе не работает, потому что методы жизненного цикла называются ранее.

4

Написать свои функции следующим образом:

onToggleLoop = (event) => { 
    this.setState({loopActive: !this.state.loopActive}) 
    this.props.onToggleLoop() 
} 

http://www.react.express/fat_arrow_functions

привязки для ключевого слова это же снаружи и внутри функции жировой стрелки. Это отличается от функций, объявленных функцией, которые могут связывать это с другим объектом при вызове. Поддержание этой привязки очень удобно для операций, таких как mapping: this.items.map (x => this.doSomethingWith (x)).

-1

Его несколько общих для отладчиков пропустить область видимости this при установке точки останова, даже при использовании вышеуказанных стратегий, чтобы связать его правильно, все равно возвращается undefined.

Иногда он связывается правильно после перекомпиляции. То есть, выключите сервер webpack и перекомпилируйте, не просто горячую перекомпиляцию.

Ложные негативы не всегда означают, что ваш код сломан.

Смежные вопросы