2017-06-05 7 views
0

Ich bin gerade dabei, unsere React-Komponenten auf ein Upgrade auf React 16 vorzubereiten, wobei der Kern dieses Prozesses ein Update von Komponenten ist, die mit das Schlüsselwort class verwenden.Wie kann ich die Ereignisbehandlungsroutinen einer React-Komponentenklasse korrekt binden, wenn ich von createClass in das Klassenschlüsselwort umwandle?

Ich habe Probleme, wenn es um Event-Handler geht, die Klassenmethoden aufrufen, da ich immer den Can only update a mounted or mounting component Fehler sehe.

Ein triviales Beispiel ...

Original-Komponente React.createClass:

const Foo = React.createClass({ 
    getInitialState() { 
    return { bar: false }; 
    }, 

    onClick() { 
    this.setState({ bar: !this.state.bar }); 
    }, 

    render() { 
    return (
     <div> 
     <p>{this.state.bar ? 'YAY' : 'BOO'}</p> 
     <button onClick={this.onClick}>CLICK IT</button> 
     </div> 
    ); 
    }, 
}); 

Das wie erwartet funktioniert. Also dies tut, wenn ich bereit bin, zu ignorieren, dass ein neues Funktionsobjekt wird bei jedem Aufruf zu render erstellt werden:

class Foo extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { bar: false }; 
    } 

    render() { 
    return (
     <div> 
     <p>{this.state.bar ? 'YAY' : 'BOO'}</p> 
     <button onClick={() => { this.setState({ bar: !this.state.bar }); }}>CLICK IT</button> 
     </div> 
    ); 
    } 
} 

aber ich kann nicht den „bind im Konstruktor“ Ansatz zu arbeiten:

class Foo extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { bar: false }; 

    this.onClick = this.onClick.bind(this); 
    } 

    onClick() { 
    this.setState({ bar: !this.state.bar }); 
    } 

    render() { 
    return (
     <div> 
     <p>{this.state.bar ? 'YAY' : 'BOO'}</p> 
     <button onClick={this.onClick}>CLICK IT</button> 
     </div> 
    ); 
    } 
} 

ich kann auch nicht die Eigenschaft initializer Syntax Ansatz an der Arbeit:

class Foo extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { bar: false }; 
    } 

    onClick =() => { 
    this.setState({ bar: !this.state.bar }); 
    } 

    render() { 
    return (
     <div> 
     <p>{this.state.bar ? 'YAY' : 'BOO'}</p> 
     <button onClick={this.onClick}>CLICK IT</button> 
     </div> 
    ); 
    } 
} 

In diesen beiden Fällen, wenn ich auf die Schaltfläche klicken die zuvor genannte Fehlermeldung zeigt i up In der Browser-Konsole.

Ich hoffe, jemand hat dieses Problem bereits selbst begegnet und hat Ratschläge, wie man damit umgeht. Ich stelle mir vor, dass es nur etwas Triviales ist, dass ich komplett übersehe. :)

Vielen Dank im Voraus!

+0

Können Sie versuchen 'onClick() { this.setState ((prevState) => ({bar: prevState.bar})); } ' –

+1

Das ist ein separates Problem; Beide Bindungsmethoden funktionieren ordnungsgemäß. –

+1

Damit die Klasseneigenschaften funktionieren, müssen Sie sie transformieren. Sie sind momentan nicht in einem Babel Preset enthalten, da sie noch ein Vorschlag sind. Sie müssen [stage-2] (https://babeljs.io/docs/plugins/preset-stage-2/) aktivieren. –

Antwort

0

Werfen Sie einen Blick auf React Documentation: Sie haben das gleiche Beispiel. Übrigens funktioniert dein Bindebeispiel für mich: poste deine Fehlermeldung.

class Toggle extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = {isToggleOn: true}; 

    // This binding is necessary to make `this` work in the callback 
    this.handleClick = this.handleClick.bind(this); 
    } 

    handleClick() { 
    this.setState(prevState => ({ 
     isToggleOn: !prevState.isToggleOn 
    })); 
    } 

    render() { 
     return (
     <button onClick={this.handleClick}> 
      {this.state.isToggleOn ? 'ON' : 'OFF'} 
     </button> 
    ); 
    } 
    } 

    ReactDOM.render(
    <Toggle />, 
    document.getElementById('root') 
); 
+0

Die Fehlermeldung ist ziemlich Standard: "Warnung: setState (...): Kann nur eine gemountete oder mounting-Komponente aktualisieren. Dies bedeutet in der Regel Sie SetState() für eine nicht eingebundene Komponente aufgerufen. Dies ist ein No-Op. Bitte überprüfen Sie die Code für die Foo-Komponente. " – natlee75

+0

Ich testete in einer Barebone-App "create-react-app" und verifizierte, dass es dort funktioniert, also ist es nur ein Problem mit der Einrichtung der App. Vielen Dank! – natlee75

0

pshh, tun Sie es einfach und react-autobind Weise. Bindet alle Komponentenfunktionen im Konstruktor automatisch an this.

Super einfach und leicht zu bedienen:

import autoBind from 'react-autobind'; 

constructor() { 
    super(); 
    autoBind(this); 
} 
+0

Das klingt nach Betrug! ;) In aller Ernsthaftigkeit, ich glaube nicht, dass das funktionieren würde. Es gibt ein Problem in der App, das ich genau ermitteln möchte. Die Syntax ist korrekt, da ich die Klasse dazu bringen kann, in einer Barebone-App "create-react-app" zu arbeiten, sodass etwas anderes passiert, was die Verbindung von React-Komponenten erschwert. – natlee75

0

Waren genau dieses Problem mit nach einigem Code von einer Elektron App auf die Bahn zu portieren.

"transform-es2015-classes" ist was Sie brauchen!

npm install --save-dev babel-plugin-transform-es2015-classes

Mehr info @ der babel docs

Verwandte Themen