单击两次时反应更新状态

时间:2019-03-26 00:03:43

标签: reactjs

在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);

4 个答案:

答案 0 :(得分:1)

问题恰恰是您链接的帖子中提到的问题。 setState是一个异步函数,不一定会在调用console.log()之前设置组件的状态。如果要在更新后查看新状态,可以向setState添加回调函数以查看状态更新的结果。

this.setState({
    text: this.state.text + emoji,
}, () => console.log(this.state.items));

编辑

以下是指向您的演示的链接,其中console.log给出了正确的结果:

https://codesandbox.io/s/949xprn3xy

答案 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 即可解决您的问题