Ik volg een beginnershandleiding van Pluralsight, op het formulier wordt een waarde doorgegeven aan de componentmethode addUser
en ik moet gebruikersnaam pushen naar this.state.users
maar 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 this
een instantie van uw class(component), en geeft het u dus geen foutmelding omdat de methode addUser
bestaat in uw klasse scope
,
maar wanneer u de methode addUser
gebruikt, gebruikt u this
om de state
bij 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 addUser
Bereik heb je niets zoals staat, gebruiker enzovoort.
Dus om dit probleem op te lossen moet je this
binden terwijl je de addUser
methode aanroept. Zodat je methode altijd de instantie van this
kent.
Dus de laatste wijziging in uw code ziet er als volgt uit:-
<Form addUser={this.addUser.bind(this)}/>
OF
U kunt this
in de constructor binden, omdat dit de plaats is waar u dingen moet initialiseren, omdat constructormethoden het eerst worden aangeroepen wanneer de componenten naar de DOM
renderen.
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 this
niet noodzakelijk de klasse is waarin de methode is gedefinieerd. Wanneer u this.addUser
gebruikt in uw <Form>
element, this
is eigenlijk het Form
object! 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 addUser
en 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 this
op 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 this
verwijzen naar het Component
object, 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 this
ergens 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