如何防止功能组件中出现重新渲染错误?

时间:2020-07-27 18:35:22

标签: javascript reactjs

我对将React Hooks与无状态组件一起使用是不熟悉的。我通常在必须使用状态时使用有状态组件。我当前的应用程序需要只能在功能组件中使用的上下文API。我已经重写了我需要工作的大多数代码,但是其中一个错误是出现了一个错误:“错误:重新渲染太多。React限制了渲染次数,以防止无限循环。”

我要转换为功能组件的组件

class pizzas extends Component {
  state ={
    pizzas: [
      {id:1, name: 'Chicken Curry', ingredients: 'Red onions, bell peppers, chicken, pineapple, mozzarella, tomato sauce, curry, chili peppers', price: '3100', image: chickenCurry },
      {id:2, name: 'Pepperoni Fresh', ingredients: 'Pepperoni, mozzarella, green peppers, pizza sauce', price: '2700', image: pepperoniFresh },
      {id:3, name: 'Chicken BBQ', ingredients: 'Chicken, red onions, corn, mozzarella, bbq sauce, tomato sauce', price: '2700', image: chickenBbq },
      {id:4, name: 'Shawarma Pizza', ingredients: 'Mayonnaise & ketchup, spicy chicken, red onions, tomatoes, mozzarella', price: '3100', image: sharwarmaPizza },
      {id:5, name: 'Chicken Suya', ingredients: 'Mayonnaise, spicy sauce, spicy chicken, bell peppers, red onions, suya sauce, tomato sauce, mozzarella, suya spice', price: '2700', image: chickenSuya },
      {id:6, name: 'Pepperoni', ingredients: 'Pepperoni, mozzarella, tomato sauce', price: '2700', image: pepperoni },
      {id:7, name: 'Beef Suya', ingredients: 'Mayonnaise, spicy sauce, spicy meatballs, bell peppers, red onions, mozzarella, suya sauce, tomato sauce, suya spice', price: '2700', image: beefSuya },
      {id:8, name: 'Chicken Supreme', ingredients: 'Spicy sauce, chicken and spicy chicken, mushrooms, bell peppers, olives, red onions, mozzarella, tomato sauce', price: '3100', image: chickenSupreme },
      {id:9, name: 'Sweet Chili Chicken', ingredients: 'Spicy sauce, chicken, chili pepper, mozzarella, sweet chili sauce, tomato sauce', price: '2700', image: chickenCurry },
      {id:10, name: 'Spicy Mixed Pizza', ingredients: 'Spicy sauce, spicy meatballs, spicy chicken, chili pepper, corn, mozzarella, buffalo sauce, tomato sauce', price: '3100', image: spicyMixedPizza },
      {id:11, name: 'Margherita', ingredients: 'Mozarella, tomato sauce', price: '2200', image: margherita },
      {id:12, name: 'Super Meaty', ingredients: 'Chicken, pepperonni, sausages, mozzarella, tomato sauce', price: '3100', image: superMeaty },
      {id:13, name: 'Cheesy Chicken', ingredients: 'Chicken, tomatoes, cheddar, mozzarella, cheese sauce', price: '2700', image: cheesyChicken },
      {id:14, name: 'Cheeseburger Pizza', ingredients: 'Beef, tomatoes, red onions, cheddar, mozzarella, mayonnaise & ketchup, tomato sauce', price: '3100', image: cheeseBurger },
      {id:15, name: 'Meaty Overload', ingredients: 'Spicy sauce, pepperonni, spicy meatballs, chicken, sausages, mozzarella, tomato sauce', price: '3400', image: meatyOverload },
      {id:16, name: 'Meaty BBQ', ingredients: 'Beef, pepperonni, sausages, mozzarella, bbq sauce, tomato sauce', price: '3100', image: meatyBbq },
      {id:17, name: 'Hawaiian', ingredients: 'Chicken, pineapple, mozzarella, sweet chili sauce, tomato sauce', price: '2700', image: hawaiian },
      {id:18, name: 'Veggie Overload', ingredients: 'Mushrooms, bell peppers, corn, olives, red onions, tomatoes, mozzarella, tomato sauce', price: '3100', image: veggieOverload }
    ],
    showModal: false,
    selectedPizza: null,
    orders: []
    
  }
  toggleModalHandler = (p)=>{
    this.setState({showModal: !this.state.showModal, selectedPizza: p});
    
  }
  addToOrders = (productName, productIngredients, productPrice, productImage, p)=>{
    this.setState(prevState=>({
      orders: [...prevState.orders, productImage, productName, productIngredients, productPrice]
    }))
  }
  render(){
  const pizza = this.state.pizzas;
  
  return (
   <Aux>
     { this.state.showModal?
       <Backdrop clicked={this.toggleModalHandler}/>: null}
   { this.state.showModal ?
    
     <Modal 
     clicked={this.toggleModalHandler}
     sendRequest={this.sendingRequestHandler}
     ingredients={this.state.selectedPizza.ingredients} 
     price={this.state.selectedPizza.price} 
     image={this.state.selectedPizza.image} 
     name={this.state.selectedPizza.name} 
     key={this.state.pizzas.id}       
     addToOrders={this.addToOrders}/>: null}
     <div className={styles.Pizza} id="pizza">
             <h1>Pizza</h1>
      <div className={styles.PizzaContainer}>
         {pizza.map(p=>{
           
    return <div>
      <div className={styles.PizzaCard}>
        <div className={styles.PizzaCardHeader}>
           <img src={p.image} alt="pizza"/>
           <h1>{p.name}</h1>
          <p>{p.ingredients}</p>
        </div>
        <div className={styles.PizzaCardFooter}>
           <h3>from ₦{p.price}</h3>
           <button onClick={()=>this.toggleModalHandler(p)}>Select</button>
        </div>  
    </div>
    </div>
  })}
      </div>
      </div>
 
  </Aux>
  )

}
}
export default pizzas;

到目前为止我所做的

const Pizzas = () => {

  const [showModal, setModal] = useState(false);
  const [selectedPizza, setSelectedPizza] = useState(null)
  const { pizzaproducts } = useContext(ProductsContext)
  const toggleModalHandler = (p) => {
    setModal(true);
    setSelectedPizza(p)
  }
  return (
    <Aux>
      {setModal(true) ?
        <Backdrop clicked={toggleModalHandler} /> : null}
      {setModal(true) ?
        <Modal
          clicked={toggleModalHandler}
          ingredients={selectedPizza.ingredients}
          price={selectedPizza.price}
          image={selectedPizza.image}
          name={selectedPizza.name}
        /> : null}
      <div className={styles.Pizza} id="pizza">
        <h1>Pizza</h1>
        <div className={styles.PizzaContainer}>
          {pizzaproducts.map(p => {

            return <div>
              <div className={styles.PizzaCard}>
                <div className={styles.PizzaCardHeader}>
                  <img src={p.image} alt="pizza" />
                  <h1>{p.name}</h1>
                  <p>{p.ingredients}</p>
                </div>
                <div className={styles.PizzaCardFooter}>
                  <h3>from ₦{p.price}</h3>
                  <button onClick={() => toggleModalHandler(p)}>Select</button>
                </div>
              </div>
            </div>
          })}
        </div>
      </div>
    </Aux>
  )
}
export default Pizzas;

我怎样才能最好地转换它?我猜这个错误是来自togglemodalhandler。我是钩子的新手。

2 个答案:

答案 0 :(得分:2)

您不应在模板内部设置状态。这将触发重新渲染,然后再次触发设置状态和下一个...

尝试这样的事情:

import React, { useState, useContext } from 'react';

const Pizzas = () => {

    const [showModal, setModal] = useState(false);
    const [selectedPizza, setSelectedPizza] = useState(null)
    const { pizzaproducts } = useContext(ProductsContext)
    const toggleModalHandler = (p) => {
        setModal(true);
        setSelectedPizza(p)
    };
    return (
        <Aux>
            {showModal ? <Backdrop clicked={toggleModalHandler} /> : null}

            {showModal ?
                <Modal
                    clicked={toggleModalHandler}
                    ingredients={selectedPizza.ingredients}
                    price={selectedPizza.price}
                    image={selectedPizza.image}
                    name={selectedPizza.name}
                /> : null}

            <div className={styles.Pizza} id="pizza">
                <h1>Pizza</h1>
                <div className={styles.PizzaContainer}>
                    {pizzaproducts.map(p => {

                        return <div>
                            <div className={styles.PizzaCard}>
                                <div className={styles.PizzaCardHeader}>
                                    <img src={p.image} alt="pizza" />
                                    <h1>{p.name}</h1>
                                    <p>{p.ingredients}</p>
                                </div>
                                <div className={styles.PizzaCardFooter}>
                                    <h3>from ₦{p.price}</h3>
                                    <button onClick={() => toggleModalHandler(p)}>Select</button>
                                </div>
                            </div>
                        </div>
                    })}
                </div>
            </div>

        </Aux>
    )
}
export default Pizzas;

答案 1 :(得分:2)

您有条件地尝试使用setModal(true)?进行渲染,这是不正确的,应该为showModal?

useState返回一对值:当前状态和一个更新状态的函数。这就是为什么我们写const [showModal, setModal] = useState()。这与类中的this.state.showModal和this.setState相似,不同之处在于它们成对出现。