简体   繁体   中英

Why am I not able to use const/let in React Component?

I have started a Reactjs project using create-react-app like before. This time it's not allowing me to use const/let in class body. I am trying to create a click handler addToCart on MdAddShoppingCart icon. If I use const or let , it says:

Failed to compile ./src/ProductListingPage.js

Line 8:11: Parsing error: Unexpected token

6 | class ProductListingPage extends React.Component { 7 | 8 | const addToCart = () => { | ^

9 | console.log("In addToCart")

10 | //store.dispatch({ type: "ADD_TO_CART" });

11 | }

and if I do not use these keywords and define function signature like this:

addToCart = () => {}

It says:

Line 24:65: 'addToCart' is not defined no-undef

I am not able to get this behavior. Any help would be appreciated. Below is the concerned code.

ProductListingPage.js

import React from 'react';
import { connect } from 'react-redux';
import { MdAddShoppingCart } from "react-icons/md";
import { Grid, Row, Col } from 'react-flexbox-grid';

class ProductListingPage extends React.Component {

addToCart = () => {
    console.log("In addToCart")
    //store.dispatch({ type: "ADD_TO_CART" });
}
render() {
    return (
        <React.Fragment>
            <h3>Product Listing Page</h3>
            <ol>
                {this.props.products.map((product, index) =>
                    <Grid fluid>
                        <Row>
                            <Col>
                                <li key={index}>{product}</li>
                            </Col>
                            <Col>
                                <MdAddShoppingCart onClick={addToCart} /> //line 24
                            </Col>
                        </Row>

                    </Grid>
                )}
            </ol>
        </React.Fragment>
    );
}
}

function mapStateToProps(state) {
return {
    ...state,
    products: state.products
};
}
export default connect(mapStateToProps)(ProductListingPage);

Package.json

      {
    "name": "cart-screen",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
      "react": "^16.12.0",
      "react-dom": "^16.12.0",
      "react-flexbox-grid": "^2.1.2",
      "react-icons": "^3.8.0",
      "react-redux": "^7.1.3",
      "react-scripts": "3.3.0",
      "reactstrap": "^8.4.0",
      "redux": "^4.0.5"
    },
    "scripts": {
      "start": "./node_modules/react-scripts/bin/react-scripts.js start",
      "start:prod": "pushstate-server build",
      "build": "./node_modules/react-scripts/bin/react-scripts.js build",
      "test": "./node_modules/react-scripts/bin/react-scripts.js test --env=jsdom",
      "eject": "./node_modules/react-scripts/bin/react-scripts.js eject",
      "server": "cd client/api && pm2 start server.js --watch",
      "proxy": "http://128.199.139.144:3000"
    },
    "browserslist": {
      "production": [
        ">0.2%",
        "not dead",
        "not op_mini all"
      ],
      "development": [
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
      ]
    }
  }

i understand what you are saying,

you can't declare addToCart with let or const because you are not dealing with functions inside a class but class methods(much similar to the object.prototype.method).

//wrong..
class x extends Component {
 let y = () => {}
}


//correct..
class x extends Component {
 y = () => {}
 z() {}
}

also, in order to use y and z. you can use this.y/z inside your jsx or you can just simply destructure it from this of that class,

constructor(props) {
super(props)
 this.z = this.z.bind(this)
}

render() {
 const { z, y } = this

 return (
  <div>
   <div onClick={() => y()} ...rest of the div.../>
   <div onClick={() => z()} ...rest of the div.../>
  </div>
 )
}

or just..

render() {
 return (
  <div onClick={() => this.y()} ..../>
  //<div onClick={this.y} ...will also do if you don't want to pass any params..../>
 )
}

since arrow function syntax doesn't have any this perspective on it's own, u can simply use it. but if you are dealing with function declarations like z , it won't inherit the this perspective from the parent so you have to bind it to the parent inside constructor..

<MdAddShoppingCart onClick={this.addToCart} />

使用它来访问类成员

You need to give the reference for addToCart function as a function defined in this Class so you need to use this.addToCart instead -:

<Col>
    <MdAddShoppingCart onClick={this.addToCart} /> //line 24
</Col>

Also const or let won't work because this is a Class not a function .

If we define something like this -:

class ProductListingPage extends React.Component {

    addToCart = () => {
        console.log("In addToCart")
    }
    render() {
        return (
            <React.Fragment>
                <h3>Product Listing Page</h3>
            </React.Fragment>
        );
    }
}

It translates to this -:

function ProductListingPage(){
    //constructor code
}

and,

ProductListingPage.prototype.addToCart = function () {
    console.log("In addToCart");
}

subsequently for the render function as well but only difference is that render function is inherited from React.Component class....

'addToCart' is a class member, somewhat like the shorthand of declaring an object method eg:

const myObj = { 
   hello() { console.log(‘world’) }
}

Which is equivalent to

const myObj = { 
   hello: function() { console.log(‘world’) }
}

It would not make sense in the context of declaring such a class member to use const or let, as you are not in a block in which variables can be declared.

However the reason your code is not working is because you need to access addToCart as a method of your class - using this.addToCart instead of just this .

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