简体   繁体   English

即使使用 React.memo,更改孩子的道具是否总是重新渲染父母?

[英]Does changing the props of a child always re-render the parent even with React.memo?

I'm trying to prevent a modal element to re-render when it's supposed to be invisible.我试图阻止模态元素在它应该不可见时重新渲染。 The course I'm following does this by converting the component to a class based component and using shouldComponentUpdate() but I wanted to check if using React.memo() did the same thing.我正在学习的课程通过将组件转换为基于 class 的组件并使用shouldComponentUpdate()来做到这一点,但我想检查使用React.memo()是否做了同样的事情。

I tried, and it doesn't, but I'm not sure why.我试过了,它没有,但我不知道为什么。

The component that should not render is this:不应该渲染的组件是这样的:

import React , {useEffect} from 'react'

import Aux from '../../../hoc/Aux';
import Backdrop from '../Backdrop/Backdrop';
import classes from './Modal.module.css';

const Modal = (props) => {
  useEffect(() => {
    console.log('[Modal.js] useEffect')
  });

  return (
    <Aux>
      <Backdrop show={props.show} clicked={props.modalClosed} />
      <div
        className={classes.Modal}
        style={{
          transform: props.show ? 'translateY(0)' : 'translateY(-100vh)',
          opacity: props.show ? '1': '0'
        }}>
          {props.children}
      </div>
    </Aux>)
  };

export default React.memo(Modal);

Which is managed by由哪个管理

import React, {Component} from 'react'

import Aux from '../../hoc/Aux';
import Burger from '../../components/Burger/Burger'
import BuildControls from '../../components/Burger/BuildControls/BuildControls'
import Modal from '../../components/UI/Modal/Modal'
import OrderSummary from '../../components/Burger/OrderSummary/OrderSummary'

const INGREDIENT_PRICES = {
  salad: 0.5,
  cheese: 0.4,
  meat: 1.3,
  bacon: 0.7
}
class BurgerBuilder extends Component {

  state = {
    ingredients: {
      salad: 0,
      bacon: 0,
      cheese: 0,
      meat: 0
    },
    totalPrice: 4,
    purchasable: false,
    purchasing: false
  }

  purchaseHandler = () => {
    this.setState({purchasing: true});
  };
  purchaseCancelHandler = () => {
    this.setState({purchasing:false});
  };
  purchaseContinueHandler = () => {
    alert('You Continue!')
  };

  updatePurchaseState = (ingredients) => {
    let purchasable = false;
    for (let ingredient in ingredients){
      if (ingredients[ingredient]>0){
        purchasable = true;
        break;
      }
    }
    this.setState({purchasable:purchasable})
  }
  addIngredientHandler = (type) => {
    const oldCount = this.state.ingredients[type];
    const updatedCount = oldCount +1;
    const updatedIngredients = {
      ...this.state.ingredients
    };
    updatedIngredients[type] = updatedCount;
    const priceAddition = INGREDIENT_PRICES[type];
    const oldPrice = this.state.totalPrice;
    const newPrice = oldPrice + priceAddition;
    this.setState({totalPrice: newPrice, ingredients: updatedIngredients});
    this.updatePurchaseState(updatedIngredients);
  };
  removeIngredientHandler = (type) => {
    const oldCount = this.state.ingredients[type];
    if (oldCount <= 0)
      return;
    const updatedCount =oldCount -1;
    const updatedIngredients = {
      ...this.state.ingredients
    };
    updatedIngredients[type] = updatedCount;
    const priceAddition =INGREDIENT_PRICES[type];
    const oldPrice = this.state.totalPrice;
    const newPrice = oldPrice - priceAddition;
    this.setState({totalPrice: newPrice, ingredients: updatedIngredients});
    this.updatePurchaseState(updatedIngredients);
  };

  render () {
    const disabledInfo = {
      ...this.state.ingredients
    };
    for (let key in disabledInfo){
      disabledInfo[key] = disabledInfo[key] <= 0;
    }
    return (
      <Aux>
        <Modal show={this.state.purchasing} modalClosed={this.purchaseCancelHandler}>
          <OrderSummary
            ingredients={this.state.ingredients}
            purchaseCancelled={this.purchaseCancelHandler}
            purchaseContinued={this.purchaseContinueHandler}
            price={this.state.totalPrice} />
        </Modal>
        <Burger ingredients={this.state.ingredients}/>
        <BuildControls
          ingredientAdded={this.addIngredientHandler}
          ingredientRemoved={this.removeIngredientHandler}
          disabled={disabledInfo}
          price={this.state.totalPrice}
          purchasable={this.state.purchasable}
          ordered={this.purchaseHandler}/>
      </Aux>
    );
  }
}

export default BurgerBuilder;

With BuildControls I change the Ingredients state;使用BuildControls ,我更改了Ingredients state; but not the props I pass to modal, purchasing and purchaseHandler但不是我传递给 modal, purchasingpurchaseHandler的道具

Does changing the ingredients prop I pass to it's child always prompt a re-render even when Modal itself is under React.memo() ?即使Modal本身在React.memo()下,更改我传递给它的孩子的成分道具是否总是提示重新渲染?

You are changing one of the props you pass to Modal - the children prop.您正在更改传递给Modal的道具之一 - children道具。 It is passed implicitly by adding children to a react element.它是通过将子元素添加到反应元素来隐式传递的。 And since you are changing the child element it will cause a re-render.并且由于您正在更改子元素,因此将导致重新渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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