Reageren op deze.state is niet gedefinieerd?

Ik volg een beginnershandleiding van Pluralsight, op het formulier wordt een waarde doorgegeven aan de componentmethode addUseren ik moet gebruikersnaam pushen naar this.state.usersmaar Ik krijg een foutmelding

App.jsx:14 Uncaught TypeError: Cannot read property 'users' of undefined

Onderdeel

import React from 'react'
import User from 'user'
import Form from 'form'
class Component extends React.Component {
    constructor() {
        super()
        this.state = {
            users: null
        }
    }
    // This is triggered on form submit in different component
    addUser(userName) { 
        console.log(userName) // correctly gives String
        console.log(this.state) // this is undefined
        console.log(this.state.users) // this is the error
        // and so this code doesn't work
        /*this.setState({
            users: this.state.users.concat(userName)
        })*/
    }
    render() {
        return (
            <div>
            <Form addUser={this.addUser}/>
            </div>
            )
    }
}
export default Component

Antwoord 1, autoriteit 100%

Wanneer u {this.addUser}aanroept, wordt het aangeroepen, hier is thiseen instantie van uw class(component), en geeft het u dus geen foutmelding omdat de methode addUserbestaat in uw klasse scope,
maar wanneer u de methode addUsergebruikt, gebruikt u thisom de statebij te werken die bestaat in
het bereik van class(component), maar momenteel ben je binnen het bereik van de addUser-methode en dus geeft het je een fout zoals onder addUserBereik heb je niets zoals staat, gebruiker enzovoort.
Dus om dit probleem op te lossen moet je thisbinden terwijl je de addUsermethode aanroept. Zodat je methode altijd de instantie van thiskent.

Dus de laatste wijziging in uw code ziet er als volgt uit:-

<Form addUser={this.addUser.bind(this)}/>

OF


U kunt thisin de constructor binden, omdat dit de plaats is waar u dingen moet initialiseren, omdat constructormethoden het eerst worden aangeroepen wanneer de componenten naar de DOMrenderen.

Dus je kunt het op deze manier doen:-

 constructor(props) {
    super(props);
    this.state = {
        users: null
    }
    this.addUser=this.addUser.bind(this);
}

En nu kun je het op de normale manier noemen zoals je eerder deed:-

<Form addUser={this.addUser}/>

Ik hoop dat dit zal werken, en ik heb het U duidelijk gemaakt.


Antwoord 2, autoriteit 12%

De aanpak van @Vinit Raj werkt perfect, hoewel ik de voorkeur geef aan de syntaxis van de pijlfunctie.

<Form addUser={ () => this.addUser() }/>

Als u een anonieme functie als deze gebruikt, hoeft u deze nergens te binden.


Antwoord 3, autoriteit 4%

Als u liever de pijlfunctie gebruikt, doet u dit. De syntaxis van de pijlfunctie zoals hieronder

addUser = event => { 
    const { value }  = event.target;
    console.log("value", value);
}

Om te voorkomen dat deze functie bij elke render of re-render wordt aangeroepen, moet je

Wijzigen

<Form addUser={this.addUser}/>

Naar

<Form addUser={() => this.addUser()}/>

Zodat addUser alleen wordt aangeroepen wanneer een gebeurtenis plaatsvindt/geactiveerd is


Antwoord 4, autoriteit 2%

Ik had hetzelfde probleem, maar ik probeerde toegang te krijgen tot this.state voordat de this.state = { ... }-aanroep was voltooid. Deed zoiets als dit this.state = { ...this.function1() }en function1 = () => { a: this.state.b }. Ik hoop dat dit iemand helpt


Antwoord 5, autoriteit 2%

In jouw geval door je functie als een dikke pijlfunctie te declareren, voeg je context toe en verwijder je de vereiste om hieraan te binden. Dit werkt precies hetzelfde als de andere oplossingen, maar maakt het schrijven en lezen een stuk eenvoudiger. Verander gewoon…

addUser(userName) { 
    console.log(userName) // correctly gives String
    console.log(this.state) // this is undefined
    console.log(this.state.users) // this is the error
    // and so this code doesn't work
    /*this.setState({
        users: this.state.users.concat(userName)
    })*/
}

naar…

addUser = (userName) => { 
    console.log(userName) // correctly gives String
    console.log(this.state) // this is undefined
    console.log(this.state.users) // this is the error
    // and so this code doesn't work
    /*this.setState({
        users: this.state.users.concat(userName)
    })*/
}

En al het andere kan hetzelfde blijven.


Antwoord 6

Ik denk niet dat de andere antwoorden dit goed uitleggen. Het probleem is eigenlijk dat het this-zoekwoord van Javascript krankzinnig is (MDN zegt heel genereus dat het “gedraagt ​​zich een beetje anders in JavaScript in vergelijking met andere talen”).

De TL;DR is dat thisniet noodzakelijk de klasse is waarin de methode is gedefinieerd. Wanneer u this.addUsergebruikt in uw <Form>element, thisis eigenlijk het Formobject! Ik weet niet zeker waarom React dit doet – ik kan niet echt bedenken waarom iemand dat zou willen, maar het is gemakkelijk te verifiëren. Plaats gewoon console.log(this)in addUseren je zult zien dat het een instantie is van Form.

Hoe dan ook, de oplossing is vrij eenvoudig: gebruik een pijlfunctie. Pijlfuncties maken een kopie van thisop het punt waar ze zijn gedefinieerd. Dus als je er een in je renderfunctie plaatst, zoals andere mensen hebben gesuggereerd:

<Form addUser={() => this.addUser()}/>

Als render()wordt uitgevoerd, zal thisverwijzen naar het Componentobject, de pijlfunctie zal er een kopie van maken, en wanneer het wordt uitgevoerd, zal het die kopie gebruiken. Het is eigenlijk een afkorting voor deze code (en dit is wat mensen vroeger deden voordat pijlfuncties):

   render() {
        const that = this; // Make a copy of this.
        return (
            <div>
            <Form addUser={function() { return that.addUser; }}/>
            </div>
            )
    }

Ook, zoals andere mensen hebben gezegd, kan het creëren van een nieuwe functie elke keer dat je je renderfunctie aanroept gevolgen hebben voor de prestaties, dus het is beter om thisergens anders vast te leggen. Ik denk dat dit een betere benadering is dan wat andere mensen hebben voorgesteld:

class Component extends React.Component {
    constructor() {
        super()
        this.state = {
            users: null
        }
    }
    // This is triggered on form submit in different component
    addUser = (userName) => { 
        this.setState({
            users: this.state.users.concat(userName)
        })
    }
    render() {
        return (
            <div>
            <Form addUser={this.addUser}/>
            </div>
            )
    }
}

Maar dit is mijn eerste dag dat ik React gebruik, en normaal probeer ik het gebruik van talen die zo blaffend zijn als Javascript te vermijden, dus neem dit alles met een korreltje zout!


Antwoord 7

Een goed patroon is om een ​​methode te binden aan de klasse in de constructorfunctie.
Zien
https://reactjs.org/docs/handling-events.html

import React from 'react'
import User from 'user'
import Form from 'form'
class Component extends React.Component {
    constructor() {
        super()
        this.state = {
            users: null
        }
  this.addUser = this.addUser.bind(this); 
  //bind functions which need access to "this"v in the constructor here. 
    }
    // This is triggered on form submit in different component
    addUser(userName) { 
        console.log(userName) // correctly gives String
        console.log(this.state) // this is undefined
        console.log(this.state.users) // this is the error
        // and so this code doesn't work
        /*this.setState({
            users: this.state.users.concat(userName)
        })*/
    }
    render() {
        return (
            <div>
            <Form addUser={this.addUser}/>
            </div>
            )
    }
}
export default Component

Antwoord 8

Het probleem zit in deze context, dus gebruik

<form onSubmit={(event)=>this.addUser(event)}>
   // Inputs
</form>
addUser(event){
   event.preventDefault()
   // Code this.state 
}

Antwoord 9

Gebruik eenvoudig async in functie

addUser =async (userName) => {
console.log(this.state.users)
}

dit werkt prima

Other episodes