简体   繁体   中英

Uncaught Reference Error: state is not defined (React.js)

Beginner here. This error keeps popping up, and I can't figure out why. My webpage does show changes that I make to the script, but only when I comment out the style to hide the shape, or keep it in to show a shape.

I'm wanting to create a webpage that, every second, changes the appearance of the shape by its size, border radius ('perCent'), and the background colour.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Timed Shapes</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 

    <style>
        .shape-item{
            padding: 10px;
            margin: 20px;
            display: inline-block;
            width: 100px;
            height: 100px;
            background-color: blue; 
            border-radius: 50%;  
        }   
    </style>
</head>
<body>
    <div class="shape-item">
        <div></div>
        <div></div>
    </div>

    <script type="text/babel">

        "use strict";

        var colours = ["#77b3d1", "#E94F37", "#1C89BF", "#A1D363", "#85FFC7", "#297373", "#FF8552", "#A40E4C", "#85AFC0", "#296573", "#AA8552", "#CC0E4C", "#567187", "#c6c976", "#967c64", "#e497ed", "#d24cff", "#e2ceb1", "#cc999e", "#97bf9a"];
        
        class Shapes extends React.Component{

            constructor(props){
                super(props);
                this.state = {
                    shape: {
                        bgColour: colours[Math.floor((Math.random() * colours.length))],
                        size: 100,
                        perCent: "%50"
                    }
                }
            }

            componentDidMount(){
                this.timerID = setInterval(() => this.updateShape(), 1000);
            }

            componentWillUnmount(){
                clearInterval(this.timerID);
            }

            updateShape(){
                let randomIndex = Math.floor((Math.random() * colours.length));
                this.setState(
                    {
                        shape: {
                            bgColour: colours[Math.floor((Math.random() * colours.length))],
                            size: (Math.random() * 125),
                            perCent: (Math.random() * 100)
                        }
                    }
                )
            }

            render(){
                var shapeStyle = {
                    padding: 10,
                    margin: 20,
                    display: 'inline-block',
                    backgroundColor: {this:state.bgColour},
                    borderRadius: {this:state.perCent},
                    width: {this:state.size},
                    height: {this:state.size}
                }
                return(
                    <div style={shapeStyle}>
                        {this.state.shape}
                    </div>
                )
            }
        }

        ReactDOM.render(<Shapes />, document.querySelector(".shape-item"));

        shapesRender = [];

        for(let i=0; i < 60; i++){
            shapesRender.push(<Shapes key={i} />);
        }

        ReactDOM.render(shapesRender, document.querySelector(".shape-item"));

    </script>
</body>
</html>

You are using colons to access the state property of this . It should be a dot. And since you are constructing a regular JS object to use for inline styles, you don't need to put the values of each key into a nested JS object, like you're doing for backgroundColor, borderRadius, width, and height. It should look like this:

var shapeStyle = {
  padding: 10,
  margin: 20,
  display: 'inline-block',
  backgroundColor: this.state.bgColour,
  borderRadius: `${this.state.perCent}%`, // append % to numerical perCent value
  width: this.state.size,
  height: this.state.size
}

An additional note, the initial value you are providing for perCent is "%50", which is a string and has a percent symbol and has it at the front, but every update, it is changed to a new Number value. I would keep it as a number from the get go (change the initial value from perCent: "%50" to perCent: 50 ) and add the percent sign in the last step where you interpolate it all into a styles object, like I did above.

And to Nick's point (in the comments on the post), if you want to display the state object in the div so you can see how the styles are affected, that's fine, but you'll need to use JSON.stringify(this.state.shape) . If you are intending for something else to display than the actual JS object, you'll need to make adjustments so you are displaying a new component or HTML element rather than just a string.

State is not defined because you used the wrong syntax ":"

Use {this.state.shape.bgColour} for {this:state.bgColour}

You can not show a object with {} in jsx:

Change {this.state.shape} to {this.state.shape.size} Change {this:state.bgColour} to {this.state.shape.bgColour} ...

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Timed Shapes</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <style>
        .shape-item{
            padding: 10px;
            margin: 20px;
            display: inline-block;
            width: 100px;
            height: 100px;
            background-color: blue;
            border-radius: 50%;
        }
    </style>
</head>
<body>
<div class="shape-item">
    <div></div>
    <div></div>
</div>

<script type="text/babel">

    "use strict";

    var colours = ["#77b3d1", "#E94F37", "#1C89BF", "#A1D363", "#85FFC7", "#297373", "#FF8552", "#A40E4C", "#85AFC0", "#296573", "#AA8552", "#CC0E4C", "#567187", "#c6c976", "#967c64", "#e497ed", "#d24cff", "#e2ceb1", "#cc999e", "#97bf9a"];

    class Shapes extends React.Component{

        constructor(props){
            super(props);
            this.state = {
                shape: {
                    bgColour: colours[Math.floor((Math.random() * colours.length))],
                    size: 100,
                    perCent: "%50"
                }
            }
        }

        componentDidMount(){
            this.timerID = setInterval(() => this.updateShape(), 1000);
        }

        componentWillUnmount(){
            clearInterval(this.timerID);
        }

        updateShape(){
            let randomIndex = Math.floor((Math.random() * colours.length));
            this.setState(
                {
                    shape: {
                        bgColour: colours[Math.floor((Math.random() * colours.length))],
                        size: (Math.random() * 125),
                        perCent: (Math.random() * 100)
                    }
                }
            )
        }

        render(){
            console.log(this.state)
            var shapeStyle = {
                padding: 10,
                margin: 20,
                display: 'inline-block',
                backgroundColor: this.state.shape.bgColour,
                borderRadius: this.state.shape.perCent,
                width: this.state.shape.size,
                height: this.state.shape.size
            }
            return(
                <div style={shapeStyle}>
                    {this.state.shape.size}
                </div>
            )
        }
    }

    ReactDOM.render(<Shapes />, document.querySelector(".shape-item"));

    let shapesRender = [];

    for(let i=0; i < 60; i++){
        shapesRender.push(<Shapes key={i} />);
    }

    ReactDOM.render(shapesRender, document.querySelector(".shape-item"));

</script>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM