0

React beginner here. Checked through similar topics and haven't found the answer. I am building a page where you create items and update information. But right now I'm struggling with a simple checkbox. When it's checked, the active state should change to true and vice versa. However, when I click, the stat doesn't change. I've checked with console log and the function works fine, tried using prevState and simple setState active:true, but I still can't change it. I'm probably missing something obvious, so thanks in advance if you can point it out.

The App Code

import React from 'react';
import './App.css';
import ProductList from "../ProductList/ProductList";
import NewProd from "../NewProd/NewProd";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
            name: "", 
            ean: "", 
            type: "", 
            weight: "", 
            color: "", 
            active: null,
            products: [{name: "Cabbage", ean: "00000000", type: "Vegetable", weight: "2kg", color: "Green", active: false}, 
            {name: "Banana", ean: "111111111", type: "Fruit", weight: "0.3kg", color: "Yellow", active: false}, 
            {name: "Chocolate", ean: "22222222222", type: "Candy", weight: "0.2kg", color: "Brown", active: false}, 
            {name: "Orange", ean: "3333333333", type: "Fruit", weight: "0.5kg", color: "Orange", active: false}, 
            {name: "Cucumber", ean: "4444444444", type: "Vegetable", weight: "1kg", color: "Green", active: false}, ]
    };
    this.isActive = this.isActive.bind(this);
};

handleFormSubmit = (e) => {
  e.preventDefault();
  let products = [...this.state.products];

  products.push({
      name: this.state.name,
      ean: this.state.ean,
      type: this.state.type,
      weight: this.state.weight,
      color: this.state.color,
      active: false,
  });
  this.setState({ products, name: "", ean: "", type: "", weight: "", color: "", active: false}
  );
}
handleInputChange = (e) => {
  let input = e.target;
  let name = e.target.name;
  let value = input.value;
  this.setState({[name]: value})
  };

deleteProduct = (delIndex) => {
  let products = [...this.state.products].filter((product, index) => index !== delIndex);
  this.setState({ products });
};
isActive = () => {
  this.setState({active: !this.state.active})
}
render() {
  return (
    <div className="App">
      <ProductList products={this.state.products} 
      deleteProduct={this.deleteProduct}
      isActive={this.isActive} />
      <NewProd handleFormSubmit={this.handleFormSubmit}
      handleInputChange={this.handleInputChange}
      newName={this.state.name}
      newEan={this.state.ean}
      newType={this.state.type}
      newWeight={this.state.weight}
      newColor={this.state.color} />
    </div>
  );
  }
}

export default App;

The List Code

import React from "react";
import "./ProductList.css";

class ProductList extends React.Component {
    render() { 
        const products = this.props.products;
        return (
            <div>
                <h1>Product List</h1>
                <table>
                    <tr>
                        <th>Name</th>
                        <th>EAN Code</th>
                        <th>Type</th>
                        <th>Weight</th>
                        <th>Color</th>
                        <th>Active</th>
                    </tr>
                    {products.map((product, index) => {
                        return (
                            <tr key={index}>
                                <td>{product.name}</td>
                                <td>{product.ean}</td>
                                <td>{product.type}</td>
                                <td>{product.weight}</td>
                                <td>{product.color}</td>
                                <td><input type="checkbox" onChange={this.props.isActive} /></td>
                                <td><button>View</button></td>
                                <td><button>Edit</button></td>
                                <td><button onClick={() => this.props.deleteProduct(index)}>Delete</button></td>
                            </tr>
                        )
                    })}
                </table>
            </div>
        )
    }
}
export default ProductList;
2
  • I see two active variable one within products and other at state level. which one you wanted to change? Commented Mar 25, 2020 at 10:45
  • The one in products. Each product is supposed to have its own active value, which starts with false and then you should click the checkbox near the product to change its active value to true. Commented Mar 25, 2020 at 11:11

2 Answers 2

3

onChange is expecting a callback function, not a boolean

as per the docs, here is the way you need to follow

<input
  name="isGoing"
  type="checkbox"
  checked={this.state.isGoing} // booean condition here for checked or not
  onChange={this.handleInputChange} />

handleInputChange(event) {
    const target = event.target;
    const value = target.name === 'isGoing' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }
Sign up to request clarification or add additional context in comments.

Comments

0

You need to update state of a product in products array. Try this:


    import React from 'react';
    import './App.css';
    import ProductList from "../ProductList/ProductList";
    import NewProd from "../NewProd/NewProd";

    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
                name: "", 
                ean: "", 
                type: "", 
                weight: "", 
                color: "", 
                active: null,
                products: [{name: "Cabbage", ean: "00000000", type: "Vegetable", weight: "2kg", color: "Green", active: false}, 
                {name: "Banana", ean: "111111111", type: "Fruit", weight: "0.3kg", color: "Yellow", active: false}, 
                {name: "Chocolate", ean: "22222222222", type: "Candy", weight: "0.2kg", color: "Brown", active: false}, 
                {name: "Orange", ean: "3333333333", type: "Fruit", weight: "0.5kg", color: "Orange", active: false}, 
                {name: "Cucumber", ean: "4444444444", type: "Vegetable", weight: "1kg", color: "Green", active: false}, ]
        };
        this.isActive = this.isActive.bind(this);
    };

    handleFormSubmit = (e) => {
      e.preventDefault();
      let products = [...this.state.products];

      products.push({
          name: this.state.name,
          ean: this.state.ean,
          type: this.state.type,
          weight: this.state.weight,
          color: this.state.color,
          active: false,
      });
      this.setState({ products, name: "", ean: "", type: "", weight: "", color: "", active: false}
      );
    }
    handleInputChange = (e) => {
      let input = e.target;
      let name = e.target.name;
      let value = input.value;
      this.setState({[name]: value})
      };

    deleteProduct = (delIndex) => {
      let products = [...this.state.products].filter((product, index) => index !== delIndex);
      this.setState({ products });
    };
    isActive = () => {
      this.setState({active: !this.state.active})
    }

    setProductActive = (product, active) => {
      this.setState((state) => ({
        products: state.products.map(p => p.name === product.name ? { ...p, active } : p)
      }))
    }

    render() {
      return (
        <div className="App">
          <ProductList products={this.state.products} 
          deleteProduct={this.deleteProduct}
          setProductActive={this.setProductActive} />
          <NewProd handleFormSubmit={this.handleFormSubmit}
          handleInputChange={this.handleInputChange}
          newName={this.state.name}
          newEan={this.state.ean}
          newType={this.state.type}
          newWeight={this.state.weight}
          newColor={this.state.color} />
        </div>
      );
      }
    }

    export default App;

import React from "react";
import "./ProductList.css";

class ProductList extends React.Component {
    render() { 
        const products = this.props.products;
        return (
            <div>
                <h1>Product List</h1>
                <table>
                    <tr>
                        <th>Name</th>
                        <th>EAN Code</th>
                        <th>Type</th>
                        <th>Weight</th>
                        <th>Color</th>
                        <th>Active</th>
                    </tr>
                    {products.map((product, index) => {
                        return (
                            <tr key={index}>
                                <td>{product.name}</td>
                                <td>{product.ean}</td>
                                <td>{product.type}</td>
                                <td>{product.weight}</td>
                                <td>{product.color}</td>
                                <td><input type="checkbox" checked={product.active} onChange={(e) => this.props.setProductActive(product, e.target.checked)} /></td>
                                <td><button>View</button></td>
                                <td><button>Edit</button></td>
                                <td><button onClick={() => this.props.deleteProduct(index)}>Delete</button></td>
                            </tr>
                        )
                    })}
                </table>
            </div>
        )
    }
}
export default ProductList;

I've added setProductActive method. Hope it can help.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.