在console.log上无法立即更新状态有一个问题,我必须在两次提交按钮上单击两次,以使console.log显示更新后的状态
我检查了这个,但我不认为这可能是问题
React: state not updating on first click
正在运行的演示,请退出控制台
https://codesandbox.io/s/l499j0p5vm?fontsize=14
这就是我拥有的
App.js
import React, {Component} from 'react';
import Navbar from './components/Navbar';
import {withStyles} from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';
import logo from './logo.svg';
import {Typography, Button} from '@material-ui/core';
import Footer from './components/Footer';
import Emoji from './components/Emoji';
import TextField from '@material-ui/core/TextField';
import EmojiPicker from 'emoji-picker-react';
import JSEMOJI from 'emoji-js';
import Icon from '@material-ui/core/Icon';
let jsemoji = new JSEMOJI();
// set the style to emojione (default - apple)
jsemoji.img_set = 'emojione';
// set the storage location for all emojis
jsemoji.img_sets.emojione.path = 'https://cdn.jsdelivr.net/emojione/assets/3.0/png/32/';
// some more settings...
jsemoji.supports_css = false;
jsemoji.allow_native = true;
jsemoji.replace_mode = 'unified'
const styles = theme => ({
shadows: ["none"],
spacing: 8,
root: {
flexGrow: 1,
minHeight: '800px',
width: '100%',
position: 'relative'
},
paper: {
padding: theme.spacing.unit * 2,
textAlign: 'left',
width: '500px',
color: theme.palette.text.secondary
},
textField: {
width: '400px'
},
myitem: {
margin: '40px'
},
emoji: {
margin: '40px'
},
emojiButton: {
margin: '20px 0px'
},
cancel: {
margin: '20px 0px'
}
});
class App extends Component {
constructor(props) {
super(props);
this.state = {
emoji: '',
text: '',
items: [],
emojiToggle: false
}
}
onChange = (e) => {
e.preventDefault()
this.setState({text: e.target.value});
}
handleClick = (n, e) => {
let emoji = jsemoji.replace_colons(`:${e.name}:`);
this.setState({
text: this.state.text + emoji,
});
// console.log(this.state.items)
}
handleButton = (e) => {
e.preventDefault();
if(!this.state.emojiToggle){
this.setState({emojiToggle: true})
}
else{
this.setState({emojiToggle: false})
}
}
onSubmit = (e) => {
e.preventDefault();
this.setState({
text: this.state.text,
items: [this.state.text]
})
console.log(this.state.items) // have to click twice to see the updated state
}
render() {
const {classes} = this.props;
return (
<div className={classes.root}>
<Navbar/>
<Grid container spacing={12}>
<Grid item sm={6} className={classes.myitem}>
<Paper className={classes.paper}>
<Typography variant="h2" component="h2">
Insert An Emoji
</Typography>
{/* Begin Form */}
<form>
<TextField
id="standard-name"
label="Enter Something"
className={classes.textField}
value={this.state.text}
onChange={this.onChange}
margin="normal"
/>
{this.state.emojiToggle ? (
<div>
<EmojiPicker onEmojiClick={this.handleClick}/>
<Button
className={classes.cancel}
onClick={this.handleButton}
color="danger"
variant="outlined">
Close
</Button>
</div>
)
: (
<div>
<Button onClick={this.handleButton} color="primary" variant="outlined">
Show Emojis
</Button>
<Button onClick={this.onSubmit} style={{ marginLeft: '10px'}} color="primary" variant="outlined">
Submit
</Button>
</div>
)}
{/* End Form */}
</form>
</Paper>
</Grid>
</Grid>
<Footer/>
</div>
);
}
}
export default withStyles(styles)(App);
答案 0 :(得分:1)
问题恰恰是您链接的帖子中提到的问题。 setState
是一个异步函数,不一定会在调用console.log()
之前设置组件的状态。如果要在更新后查看新状态,可以向setState
添加回调函数以查看状态更新的结果。
this.setState({
text: this.state.text + emoji,
}, () => console.log(this.state.items));
编辑
以下是指向您的演示的链接,其中console.log
给出了正确的结果:
答案 1 :(得分:1)
Console.log()执行在状态完成更新之前。 因为setState()是异步函数
this.setState({
text: this.state.text,
items: [this.state.text]
}, () => console.log(this.state.items));
答案 2 :(得分:0)
这是预期的行为。 console.log()
是同步的,因此它在setState()
完成之前运行。如果您确实想查看当前状态,则应将提交处理程序更改为:
onSubmit = e => {
e.preventDefault();
this.setState(
{
text: this.state.text,
items: [this.state.text]
},
() => console.log(this.state.items)
);
};
答案 3 :(得分:-1)
只需在函数之前使用 async ,在 setState 之前使用 await 即可解决您的问题