简体   繁体   English

在 React 中更新子道具组件后更改父 state?

[英]Changing parent state after updating childs prop component in React?

I'm newish to react.我是新来的反应。 I have a fetch call in my App Component that I assign to a state.我的应用程序组件中有一个 fetch 调用,我分配给 state。 I pass that state as a prop along with a function to make a post to a child component.我将 state 作为道具与 function 一起传递给子组件。 In my child component you can post/delete to alter the props, currently don't have a push() to add the new contact/prop.在我的子组件中,您可以发布/删除以更改道具,目前没有 push() 来添加新的联系人/道具。 Is there a way to alter the parent component's state after I change the childs props?更改子道具后,有没有办法更改父组件的 state? is there a better way to do this?有一个更好的方法吗?

I'm trying to get the post action to update the state on the App.我正在尝试获取发布操作以更新应用程序上的 state。

App code应用代码

class App extends Component {

  constructor() {
    super();
    this.state= {
      contacts:[], 
      addModalShow: false,
      modalIsOpen: false
    }
  }

  componentDidMount() {
      var request = new Request('http://localhost:3000/', {
          method: "GET",
      });
      fetch(request)
          .then((res) => {
              res.json()
                  .then((data) => {
                      this.setState({
                        contacts: data.rows
                      })
                  })
          })
  }

  toggleModal() {
    this.setState({
        modalIsOpen: ! this.state.modalIsOpen
    })
}

  addContact(event) {
        this.toggleModal()
        event.preventDefault();
        let contactData = {
            first: this.refs.first.value,
            last: this.refs.last.value,
            phone: this.refs.phone.value,
            email: this.refs.email.value,
        };
        var request = new Request('http://localhost:3000/add', {
            method: "POST",
            headers: new Headers({ 'Content-Type': 'application/json' }),
            body: JSON.stringify(contactData)
        });

        console.log(this.state)

        fetch(request)
            .then((res) => {
                res.json()
                    .then((data) => {
                    })
            })
            .catch((err) => {
                console.log(err)
            })
    }

  render() {

    return (
      <Container>
        {console.log(this.state)}
        <AddContact  addContact={this.addContact} contacts={this.state.contacts} />
        <ContactList contacts={this.state.contacts} />
        <Contacts contacts={this.state.contacts}/>

      </Container>
    );
  }
}

export default App;

Child component子组件

class AddContact extends Component {
    constructor(props) {
        super(props);
        this.state = {
            contacts: [],
            modalIsOpen: false,
        }
    }

    toggleModal() {
        this.setState({
            modalIsOpen: ! this.state.modalIsOpen
        })
    }


    render() {
        return(
            <Container>
                <div className='header'>
                    <h1>
                        My Contacts
                        <button className='addContactButton' onClick={this.toggleModal.bind(this)}>+</button>
                    </h1>
                    <hr />
                </div>
                <Modal isOpen={this.state.modalIsOpen}>
                <form ref='addContact' >
                    <div className='addContactHeader'>
                        <button className='saveButton' onClick={this.props.addContact.bind(this)}>Save</button>
                        <button className='cancelButton' onClick={this.toggleModal.bind(this)}>Cancel</button>
                    </div>
                    <div id="circle">
                        Add Photo
                    </div>
                    <div className="inputFields">
                        <div className='nameInputs'> 
                            <input type='text' ref='first' placeholder='first name' />
                            <input type='text' ref='last' placeholder='last name' />
                        </div>
                        <div className='extraInputs' >
                            <input type='text' ref='phone' placeholder='phone' />
                            <input type='text' ref='email' placeholder='email' />
                        </div>
                    </div>
                </form>

                </Modal>
          </Container>
        )
    }  
}

Thanks for your time谢谢你的时间

You could use a callback function in order to update the state on the parent component (Another approach would be to use Redux updating the value in the Store, that way both components could have access to the value), here's how you could use the callback (With a little bit of ES6 refactor):您可以使用回调 function 来更新父组件上的 state (另一种方法是使用 Redux 来更新存储中的值) (通过一点 ES6 重构):

App:应用程序:

class App extends Component {
  state= {
    contacts:[], 
    addModalShow: false,
    modalIsOpen: false
  }

  componentDidMount() {
    let request = new Request('http://localhost:3000/', {
        method: "GET",
    });

    fetch(request)
        .then((res) => {
            res.json()
                .then((data) => { this.setState({ contacts: data.rows }) })
        })
   }

  toggleModal = () => {
    this.setState({ modalIsOpen: ! this.state.modalIsOpen })
  };

  addContact = event => {
        this.toggleModal()
        event.preventDefault();
        let contactData = {
            first: this.refs.first.value,
            last: this.refs.last.value,
            phone: this.refs.phone.value,
            email: this.refs.email.value,
        };
        let request = new Request('http://localhost:3000/add', {
            method: "POST",
            headers: new Headers({ 'Content-Type': 'application/json' }),
            body: JSON.stringify(contactData)
        });

        fetch(request)
            .then((res) => {
                res.json()
                    .then((data) => {
                    })
            })
            .catch((err) => {
                console.log(err)
            })
    };

  changeContacts = (newData) => {
    this.setState({ contacts: newData });
  };

  render() {
    const { contacts } = this.state; 

    return (
      <Container>
        <AddContact
          addContact={this.addContact}
          contacts={contacts}
          onChildAction={this.changeContacts}
        />
        <ContactList contacts={contacts} />
        <Contacts contacts={contacts}/>
      </Container>
    );
  }
}

export default App;

AddContacts:添加联系人:

class AddContact extends Component {
    state = {
      contacts: [],
      modalIsOpen: false,
    }

    toggleModal = () => {
        this.setState({ modalIsOpen: ! this.state.modalIsOpen })
    };

    // Here is where you'll send the info for the change of the prop
    changeProp = e => {
      const { onChildAction } = this.props;
      onChildAction('Your new state/prop value here')
      addContact(e);
    };

    render() {
    const { changeProp } = this.props;
    const { modalIsOpen } = this.state;

    return(
      <Container>
        <div className='header'>
          <h1>My Contacts
            <button className='addContactButton' onClick={this.toggleModal}>+</button>
          </h1>
          <hr />
        </div>
        <Modal isOpen={modalIsOpen}>
          <form ref='addContact' >
            <div className='addContactHeader'>
              <button className='saveButton' onClick={changeProp}>Save</button>
              <button className='cancelButton' onClick={this.toggleModal}>Cancel</button>
             </div>
             <div id="circle">Add Photo</div>
             <div className="inputFields">
               <div className='nameInputs'> 
                 <input type='text' ref='first' placeholder='first name' />
                 <input type='text' ref='last' placeholder='last name' />
               </div>
               <div className='extraInputs' >
                 <input type='text' ref='phone' placeholder='phone' />
                 <input type='text' ref='email' placeholder='email' />
               </div>
             </div>
           </form>
         </Modal>
      </Container>
    )
  }  
}

The last thing you need to do is decide where you want the change of the state/prop to be fire.您需要做的最后一件事是决定您希望在哪里触发状态/道具的更改。 Hope this helps.希望这可以帮助。

to handle the parent from child you need to bind this to the child要处理来自孩子的父母,您需要将其绑定this孩子

Parent Component父组件

    class Component extends React.Component {
          constructor(props) {
            super(props)
            this.state= {
              contacts:[], 
              addModalShow: false,
              modalIsOpen: false
            }
            this.addContact = this.addContact.bind(this);
        }
          render() {
...
            return <AddContact addContact = {this.addContact} />
          }
        addContact(event) {
          ...
          alert('one contact added');
          ...}
        }

inside AddContact Component:在 AddContact 组件内:

you can call this.props.addContact() to excute the parent function你可以调用this.props.addContact()来执行父 function

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

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