简体   繁体   中英

Update state when props change

I have a problem with update props.


I have two components .

The first is the App, where there is a button that opens or closes the modal.

The second is the modal structure.
The first component stores the state, I click the buton, the state changes, I send props to ModalComponent component (the modal is opening).
And in this component should change this state if I want to close modal.
But if I click on the Cancel button in modal, nothing happens.
The state does not change.

How to change it, how it would make communication between the child and the parent?

This is my code : ModalComponent

import React, { Component } from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";

class ModalComponent extends Component {
  constructor(props) {
    super(props);

    this.state = {
      modal: props.modal
    };

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

  toggle() {
    const { modal } = this.state;
    this.setState({
      modal: !modal
    });
  }

  render() {
    const { modal } = this.props;
    return (
      <div>
        <Modal isOpen={modal} toggle={this.toggle}>
          <ModalHeader toggle={this.toggle}>Halo</ModalHeader>
          <ModalFooter>
            <Button onClick={this.toggle}>Cancel</Button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default ModalComponent;

App

import React from "react";
import ReactDOM from "react-dom";
import Modal from "./modal";
import { Button } from "reactstrap";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      modal: false
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle() {
    const { modal } = this.state;
    this.setState({
      modal: !modal
    });
  }

  render() {
    const { modal } = this.state;
    return (
      <div>
        <Button
          type="link"
          onClick={this.toggle}
        >
          Delete account
        </Button>
        <Modal modal={modal} />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

The state in your Modal Component would change but you aren't using it to set the isOpen props on Modal component.

Also you must not use state which is directly derivable from props. You must instead pass a handler from Parent to update the state in the parent itself

ModalComponent

import React, { Component } from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";

class ModalComponent extends Component {
  render() {
    const { modal } = this.props;
    return (
      <div>
        <Modal isOpen={modal} toggle={this.toggle}>
          <ModalHeader toggle={this.props.toggle}>Halo</ModalHeader>
          <ModalFooter>
            <Button onClick={this.props.toggle}>Cancel</Button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default ModalComponent;

App

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      modal: false
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle() {
    const { modal } = this.state;
    this.setState({
      modal: !modal
    });
  }

  render() {
    const { modal } = this.state;
    return (
      <div>
        <Button
          type="link"
          onClick={this.toggle}
        >
          Delete account
        </Button>
        <Modal modal={modal} toggle={this.toggle}/>
      </div>
    );
  }
}

The way you have it now, the modal is setting its own state, but it is still receiving a prop from the parent, which is keeping it open.

Here's an example of one way to do it. Note that both opening and closing is dealt with using the state of the parent, not the state of the child.

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  state = { open: false };

  toggle = () => {
    this.setState({ open: !this.state.open });
  };

  render() {
    return (
      <React.Fragment>
        something
        <Modal show={this.state.open} />
        <Child toggle={this.toggle} />
      </React.Fragment>
    );
  }
}

const Child = ({ toggle }) => {
  return <button onClick={toggle}>toggle</button>;
};

const Modal = ({ show }) => {
  if (show) {
    return <h1>I am a modal</h1>;
  }

  return null;
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CodeSandbox here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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