使用复选框 React 更改对象属性的值

吉斯伯茨

我对做出反应还很陌生,并且真的被困在了某些事情上。我正在研究一种订购应用程序。人们可以订购产品并可以选择他们想要的所有成分。我想用每个成分的复选框来做到这一点。不幸。我只是不知道如何解决这个问题。另外,我想知道是否必须在组件中使用状态或仅使用变量。

因此,我正在映射成分数组,并为每种成分显示一个复选框以打开/关闭成分。所以我的主要问题是,如何使用这些复选框调整我的对象,如果我需要在我的组件中有一个状态以与复选框保持同步,我将如何将产品设置为我的状态?因为它来自道具。

我已经尝试了各种各样的东西,例如文档中的这个:

  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

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

    this.setState({
      [name]: value
    });
  }

但话说回来,如何将产品添加到我的状态?此外,这将有所不同,因为成分在一个对象中,并且文档中的示例只是值而不是在特定对象中。

我的组件

import React from 'react';
import { Link } from 'react-router-dom';

class Order extends React.Component {

    constructor(props) {
        super(props);
    }

    handleToggle(e) {

        //Handle the toggle, set the value of the ingredient to 0 or 1

    }

    getData(e, product) {

        e.preventDefault();

        console.log(product)

    }

    render() {

        const product = this.props.products.find((product) => {
            return product.id == this.props.match.params.id;
        });

        return (

            <form className="container mx-auto px-4 pt-6" onSubmit={(e) => this.getData(e, product) }>

                <Link to={`/${this.props.match.params.category}`} className="mb-4 relative block text-brand hover:text-brand-dark">&larr; Terug naar categorie</Link>

                <div className="flex flex-row items-center justify-between bg-white rounded px-8 py-8 shadow-sm mb-4">

                    <div className="">
                        <h2 className="text-brand uppercase">{product && product.name}</h2>
                        <div className="ingre">
                            <p>
                                {product && product.ingredients.map((item) => {
                                    return <span className="ing text-grey-dark text-sm" key={item.name}>{item.name}</span>
                                })}
                            </p>
                        </div>
                    </div>

                    <div className="">
                        <h3 className="text-brand text-4xl">&euro;{product && product.price}</h3>
                    </div>

                </div>

                <div className="flex flex-wrap mb-4 -mx-2">

                    {product && product.ingredients.map((item) => {
                        return (
                            <div className="w-1/2 mb-4 px-2" key={item.name}>
                                <div className="flex flex-row items-center justify-between bg-white rounded px-8 py-8 shadow-sm">
                                    <div>
                                        <h3 className="text-grey-dark font-normal text-sm">{item.name}</h3>
                                    </div>
                                    <div>
                                        <input type="checkbox" checked={item.value} name={item} onChange={(e) => this.handleToggle(e)}/>
                                    </div>
                                </div>
                            </div>
                        );
                    })}

                </div>

                <button type="submit" className="bg-brand hover:bg-brand-dark text-white font-bold py-4 px-4 rounded">
                    Order this product
            </button>

            </form>

        );

    }

}

export default Order;

产品示例

在此处输入图片说明

所以实际上我需要跟踪产品并将成分的值绑定到复选框。如果未检查,则该值必须变为 0(或 false)。

编辑:

父组件传递道具

// React deps
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";

// Custom components
import Navigation from './components/General/Navigation'

// Pages
import Index from './components/Index'
import Category from './components/Category'
import Order from './components/Order'

// Data
import products from './Data'

class App extends Component {

  constructor(props) {

    super(props);

    this.state = {
      products: []
    }

  }

  componentWillMount() {

    setTimeout(() => {
      this.setState({products});
    }, 100);

  }

  render() {
    return (
      <main className="App font-sans">
        <Router>
          <div>

            <Navigation logo="Jackies" />
            <Switch>
              <Route exact path="/" component={Index} />
              <Route exact path="/:category" render={(props) => <Category {...props} products={this.state.products} />}/>
              <Route exact path="/:category/:id" render={(props) => <Order {...props} products={this.state.products} />}/>
            </Switch>

          </div>
        </Router>

      </main>
    );
  }
}

export default App;
辅助

在父级中,您将在onIngredientToggleprop 中传递一个处理程序函数

<Route exact path="/:category/:id" render={(props) => <Order {...props} products={this.state.products} onIngredientToggle={this.handleIngredientToggle} />}/>

然后定义handleIngredientToggle函数:

function handleIngredientToggle(productId, ingredientIndex, newIngredientValue) {
    // basically this goes shallow cloning the objects and arrays up to
    // the point it changes the ingredient value property
    let products = [...this.state.products];
    let modifiedProductIndex = products.findIndex(p => p.id === productId);
    let product = {...products[modifiedProductIndex]};
    products[modifiedProductIndex] = product;
    product.ingredients = [...products[modifiedProductIndex].ingredients];
    product.ingredients[ingredientIndex] = {...product.ingredients[ingredientIndex], value: newIngredientValue};

    this.setState({products});
}

// If you prefer, the above function can be replaced with:
function handleIngredientToggle(productId, ingredientIndex, newIngredientValue) {
    // deep clone products
    let products = JSON.parse(JSON.stringify(this.state.products));
    // modify just what changed
    products.find(p => p.id === productId).ingredients[ingredientIndex].value = newIngredientValue;

    this.setState({products});
}

Order孩子中,您将把index参数添加map(您有两个,只需添加到第二个):

{product && product.ingredients.map((item, index) => {

在复选框中将product作为参数传递indexhandleToggle函数:

<input type="checkbox" checked={item.value} name={item} onChange={(e) => this.handleToggle(e, product, index)}/> 

然后在函数实现中,您将调用从父级作为 prop 接收的函数:

handleToggle(e, product, index) {
    this.props.onIngredientToggle(product.id, index, e.target.checked);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章