简体   繁体   English

回调函数,负责更新状态,作为道具传递给子组件,而不触发状态更新

[英]Callback function, responsible for updating state, passed as props to child component not triggering a state update

The callback function (lies in Images component) is responsible for making a state update. 回调函数(位于Images组件中)负责进行状态更新。 I'm passing that function as props to the Modal component, and within it it's being passed into the ModalPanel component. 我将该功能作为道具传递给Modal组件,并且在其中将其传递给ModalPanel组件。

That function is used to set the state property, display, to false which will close the modal. 该函数用于将状态属性display设置为false,这将关闭模式。 Currently, that function is not working as intended. 当前,该功能无法正常工作。

Image Component: 图片组件:

class Images extends Component {
  state = {
    display: false,
    activeIndex: 0
  };

  handleModalDisplay = activeIndex => {
    this.setState(() => {
      return {
        activeIndex,
        display: true
      };
    });
  };

  closeModal = () => {
    this.setState(() => {
      return { display: false };
    });
  }

  render() {
    const { imageData, width } = this.props;
    return (
      <div>
        {imageData.resources.map((image, index) => (
          <a
            key={index}
            onClick={() => this.handleModalDisplay(index)}
          >
            <Modal
              closeModal={this.closeModal}
              display={this.state.display}
              activeIndex={this.state.activeIndex}
              selectedIndex={index}
            >
              <Image
                cloudName={CLOUDINARY.CLOUDNAME}
                publicId={image.public_id}
                width={width}
                crop={CLOUDINARY.CROP_TYPE}
              />
            </Modal>
          </a>
        ))}
      </div>
    );
  }
}

export default Images;

Modal Component: 模态分量:

const overlayStyle = {
  position: 'fixed',
  zIndex: '1',
  paddingTop: '100px',
  left: '0',
  top: '0',
  width: '100%',
  height: '100%',
  overflow: 'auto',
  backgroundColor: 'rgba(0,0,0,0.9)'
};

const button = {
  borderRadius: '5px',
  backgroundColor: '#FFF',
  zIndex: '10'
};

class ModalPanel extends Component {
  render() {
    const { display } = this.props;
    console.log(display)
    const overlay = (
      <div style={overlayStyle}>
        <button style={button} onClick={this.props.closeModal}>
          X
        </button>
      </div>
    );
    return <div>{display ? overlay : null}</div>;
  }
}

class Modal extends Component {
  render() {
    const {
      activeIndex,
      children,
      selectedIndex,
      display,
      closeModal
    } = this.props;
    let modalPanel = null;
    if (activeIndex === selectedIndex) {
      modalPanel = (
        <ModalPanel display={this.props.display} closeModal={this.props.closeModal} />
      );
    }

    return (
      <div>
        {modalPanel}
        {children}
      </div>
    );
  }
}

export default Modal;

links to code https://github.com/philmein23/chez_portfolio/blob/chez_portfolio/components/Images.js 链接到代码https://github.com/philmein23/chez_portfolio/blob/chez_portfolio/components/Images.js

https://github.com/philmein23/chez_portfolio/blob/chez_portfolio/components/Modal.js https://github.com/philmein23/chez_portfolio/blob/chez_portfolio/components/Modal.js

You're dealing with this modal through a very non-react and hacky way. 您正在通过一种非反应性和低调的方式来处理这种模式。

Essentially, in your approach, all the modals are always there, and when you click on image, ALL modals display state becomes true, and you match the index number to decide which content to show. 本质上,在您的方法中,所有模态始终存在,并且当您单击图像时, 所有模态的display状态变为true,并且您与索引号匹配以决定要显示的内容。 I suspect it's not working due to the multiple children of same key in Modal or Modal Panel. 我怀疑由于Modal或Modal Panel中有多个同一个键的子代而无法正常工作。

I strongly suggest you to ditch current approach. 我强烈建议您放弃当前的方法。 Here's my suggestions: 这是我的建议:

  1. Only a single <Modal/> in Images component. Images组件中只有一个<Modal/>
  2. Add selectedImage state to your Images component. selectedImage状态添加到您的Images组件。 Every time you click on an image, you set selectedImage to that clicked image object. 每次单击图像时,都将selectedImage设置为该单击的图像对象。
  3. Pass selectedImage down to Modal to display the content you want. selectedImage向下传递给Modal以显示所需的内容。

This way, there is only ONE modal rendered at all time. 这样,在任何时候都只渲染一个模态。 The content changes dynamically depending on what image you click. 内容根据您单击的图像而动态变化。

This is the working code I tweaked from your repo: 这是我从您的仓库中调整的工作代码:

(I'm not sure what to display as Modal content so I display public_id of image) (我不确定显示什么为模态内容,所以我显示图像的public_id

Images Component 图片组件

class Images extends Component {
  state = {
    display: false,
    selectedImage: null
  };

  handleModalDisplay = selectedImage => {
    this.setState({
      selectedImage,
      display: true
    })
  };

  closeModal = () => {
    //shorter way of writing setState
    this.setState({display: false})
  }

  render() {
    const { imageData, width } = this.props;
    return (
      <div>
        <Modal
          closeModal={this.closeModal}
          display={this.state.display}
          selectedImage={this.state.selectedImage}
        />
        {imageData.resources.map((image, index) => (
          <a
            //Only use index as key as last resort
            key={ image.public_id }
            onClick={() => this.handleModalDisplay(image)}
          >
            <Image
              cloudName={CLOUDINARY.CLOUDNAME}
              publicId={image.public_id}
              width={width}
              crop={CLOUDINARY.CROP_TYPE}
            />
          </a>
        ))}
      </div>
    );
  }
}

Modal Component 模态分量

class Modal extends Component {
  render() {
    const { display, closeModal, selectedImage } = this.props;

    const overlayContent = () => {
      if (!selectedImage) return null; //for when no image is selected
      return (
        //Here you dynamically display the content of modal using selectedImage
        <h1 style={{color: 'white'}}>{selectedImage.public_id}</h1>
      )
    }

    const overlay = (
      <div style={overlayStyle}>
        <button style={button} onClick={this.props.closeModal}>
          X
        </button>
        {
          //Show Modal Content
          overlayContent()
        }
      </div>
    );
    return <div>{display ? overlay : null}</div>;
  }
}

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

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