J'essaie de rapporter des composants dans Tout d'abord, j'envoie le nom d'utilisateur et le mot de passe de ceci est rendu dans App.js ici: p> Il doit appeler la fonction de connexion dans App.js (qui est terminée parce que I console.log (nom d'utilisateur) et il est reçu): p> Lorsque cela est fait, connecté devrait devenir vrai, ce qui rend le L'état initial de l'application.js est-ce: p> app.js code> lorsqu'un utilisateur se connecte mais quand i setState code> dans app.js code> (IN Commande de restituer des composants), l'état ne change pas d'une autre login.js code> à app.js code> ici: p> lightningtalkcomponent code > Dans app.js code> (voir aussi): p> import React from 'react';
import LightningTalk from './components/lightning-talk-component.js';
import Form from './components/form.js';
import Login from './components/login.js';
import './App.css'
// initialized state of App to hold an empty lightningTalks compoennt. componentDidMount sets its state depends
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
lightningTalks: [],
username: "",
loggedIn: false
};
}
// componentDidMount is called and sets the state of the lightningTalks array in constructor(props)
componentDidMount = () => {
fetch("http://localhost:4000/talks.json")
.then(response => response.json())
.then((data) => {
// sorts the data when component mounts from largest to smallest votes
data.sort((a, b) => b.votes - a.votes)
this.setState((state) => {
return {
lightningTalks: data
};
});
});
}
// sends a post request to the API
postInApp = (titleDescription) => {
const talk = {}
talk.title = titleDescription.title
talk.description = titleDescription.description
talk.votes = 0
fetch("http://localhost:4000/talks", {
headers: {
"Content-Type": "application/json"
},
method: "POST",
body: JSON.stringify({ "talk": talk })
})
.then(response => response.json())
.then((data) => {
console.log(data);
});
}
login = (username) => {
console.log('username', username)
console.log('username state', this.state.username)
this.setState({
loggedIn: true,
username: username
});
console.log('username', username)
console.log('username state', this.state.username)
console.log('logged in state', this.state.loggedIn)
}
// increments/decrements the votes in an object of lightningTalks
incrementInApp = (id) => {
// creates a new array based off current state of lightningTalks
const nextLightningTalks = this.state.lightningTalks.map((currentLightningTalk) => {
// if the id in the parameters equals the id of the current objects ID then place back into the array
if (currentLightningTalk.id !== id) {
return currentLightningTalk
}
// whatever remains (the one whose ID does match), += 1 votes of that object
const nextLightningTalk = {...currentLightningTalk, votes: currentLightningTalk.votes + 1,
};
return nextLightningTalk
})
// sorts when number of votes increases
nextLightningTalks.sort((a, b) => b.votes - a.votes)
// set new state of lightningTalks to equal the result of the new array above (the .map)
this.setState({lightningTalks: nextLightningTalks})
}
decrementInApp = (id) => {
const nextLightningTalks = this.state.lightningTalks.map((currentLightningTalk) => {
if (currentLightningTalk.id !== id) {
return currentLightningTalk
}
const nextLightningTalk = {...currentLightningTalk, votes: currentLightningTalk.votes - 1,
};
return nextLightningTalk
})
// sorts when number of votes decreases
nextLightningTalks.sort((a, b) => b.votes - a.votes)
this.setState({lightningTalks: nextLightningTalks})
}
lightningTalkRender(props) {
return <div className="talks">
{this.state.lightningTalks.votes}
{this.state.lightningTalks.map((talk) => {
return <LightningTalk lightningTalk={talk} incrementInApp={this.incrementInApp} decrementInApp={this.decrementInApp}/>
})}
</div>
}
// now the state of lightning talks depends on what is on the API. Below there is a loop(.map) which is set by componentDidMount
render() {
return (
<div className="container">
<h1>Lightning Talks!</h1>
<Login login={this.login}/>
{this.state.loggedIn ? <lightningTalkRender/> : null}
<h3 className="form-header"> Submit your talk</h3>
<Form postInApp={this.postInApp}/>
</div>
)
}
}
export default App;
import React from "react"
import './login.css';
class Login extends React.Component {
constructor(props) {
super(props);
this.loginSubmit = this.loginSubmit.bind(this)
this.state = {
username: '',
password: '',
errors: [],
pwdStrength: null
}
}
showValidationErr (e, msg) {
this.setState((prevState) => ( { errors: [...prevState.errors, { e, msg }] } ));
}
clearValidationErr (e) {
this.setState((prevState) => {
let newArr = [];
for(let err of prevState.errors) {
if(e !== err.e) {
newArr.push(err);
}
}
return {errors: newArr};
})
}
onUsernameChange= (e) => {
this.setState({ username: e.target.value })
this.clearValidationErr("username");
}
onPasswordChange= (e) => {
this.setState({ password: e.target.value })
this.clearValidationErr("password");
// set state of password strength based on length. Render these as CSS below
if (e.target.value.length <= 8) {
this.setState({ pwdStrength: "pwd-weak"})
} if (e.target.value.length > 8) {
this.setState({ pwdStrength: "pwd-medium" })
} if (e.target.value.length > 12) {
this.setState({ pwdStrength: "pwd-strong" })
}
}
// on submit, time is logged (new Date) and state of title and description is changed
loginSubmit= (e) => {
e.preventDefault()
if(this.state.username === "") {
this.showValidationErr("username", "Username cannot be empty")
} if (this.state.password === "") {
this.showValidationErr("password", "Password cannot be empty")
}
const username = this.state.username
this.props.login(username)
// call onSubmit in LightningTalk so that new talk is added from form
// this.props.postInApp(usernamePassword)
}
render() {
let usernameErr = null;
let passwordErr = null;
for(let err of this.state.errors) {
if(err.e === "username") {
usernameErr = err.msg
} if (err.e === "password") {
passwordErr = err.msg
}
}
return (
<form className="form-container">
<label>
<p className="form-title">Username:</p>
<input className="input-username"
placeholder="enter your username"
value={this.state.username}
onChange={this.onUsernameChange}
/>
<small className = "danger-error"> { usernameErr ? usernameErr : "" }</small>
</label>
<br />
<label>
<p className="form-description">Password:</p>
<input className="input-password"
placeholder="enter your password"
value={this.state.password}
onChange={this.onPasswordChange}
type="password"
/>
<small className="danger-error"> { passwordErr ? passwordErr : "" }</small>
{this.state.password && <div className="password-state">
<div
className={"pwd " + (this.state.pwdStrength)}></div>
</div>}
{/*when the button is clicked, call the loginSubmit function above. E (event) is passed into loginSubmit function (above)*/}
</label>
<br />
<button onClick={e => this.loginSubmit(e)}>Login</button>
</form>
);
}
}
export default Login;
3 Réponses :
setState code> est async.iSi vous souhaitez voir l'état après la définition d'une fonction de rappel <Login login={(username) => this.login(username)}/>
Merci pour cette suggestion. Comment utiliser cela pour arriver à la source du problème?
Une fois que vous êtes sûr d'avoir les bonnes valeurs dans votre état, vous pouvez expliquer davantage votre méthode de connexion.
Je vois. Donc, je suis sûr que les bonnes valeurs proviennent de la méthode de connexion - c'est juste que l'état n'est pas mis à jour. Avez-vous une idée pourquoi?
Merci encore pour votre aide. Cela ne fonctionne toujours pas. D'autres suggestions?
login = (username) => {
this.setState({
loggedIn: true,
username: username
});
console.log('username state', this.state.username)
console.log('logged in state', this.state.loggedIn)
}
You expect the state to have the new values when you console log above, but that is not how state works in React. React batches state updates, so when you call setState, the state is not updated immediately. Inside the login function, state.loggedIn will always have the old value. You have to wait for a rerender before the value is changed.Is your component rerendering? Or are you assuming that state is not updating because when you console log, the state has the old value?Try putting a console log in the top of your render function, and see if the new state gets logged correctly there, as the component will rerender with the new state.
Intéressant, merci pour cela. Quand je console.log en rendu, il montrent. Cela signifie donc que j'ai besoin de renverser la composante, non?
Je suis nouveau pour réagir et coder, donc pas sûr de quoi faire
Le composant redevient automatiquement lorsque l'état est mis à jour.
HILLYBOB991, comme indiqué dans ReactJS Docs. La fonction STSTATE () est une fonction ASYNC et votre code continue donc à votre relevé de journal, même avant que l'instate est exécutée.
login = (username) => {
console.log('username', username)
console.log('username state', this.state.username)
this.setState({
loggedIn: true,
username: username
}, () => {
//WHATEVER YOU WANT TO BE EXECUTED AFTER SETTING STATE..
//MAY BE YOUR CONSOLE LOG STATEMENT TOO
const username = this.state.username
this.props.login(username)
});
Merci pour ça. Donc, le problème est que l'État ne met pas à jour initialement. Comment puis-je obtenir l'état de mettre à jour? Pour le moment il ne le fait pas
@ HILLYBOB991, l'État met à jour sur la go, c'est juste qu'il a le format ASYNC !! Tout ce que vous avez à faire est de mettre votre code de code suivant comme une fonction de rappel dans la fonction SetState elle-même!
Merci, je comprends simplement cette pièce de code figure dans le fichier App.js et non le composant de connexion. Dois-je littéralement cela dans le fichier login.js alors? Désolé, je suis nouveau à coder et à réagir, alors pas sûr!
@ HILLYBOB991, comme je peux voir dans le code intégral est ici i> une partie de votre code. Votre état est dans votre fichier login.js !! Alors oui cela va dans votre fichier login.js! Où vous pouvez définir le nouvel état, puis procéder plus loin avec ce nouvel état via la fonction de rappel. Et ne vous inquiétez pas, nous sommes ici pour s'entraider!
Merci pour cette ashutosh. Malheureusement, cela ne fonctionne toujours pas. Avez-vous d'autres suggestions?
@ hillybob991! Désolé mon pote c'est tout ce que j'avais.
Vous pouvez renvoyer Stackoverflow.com/questions/42038590 / ...