如何在Reactjs中将数据从子组件发送到父组件状态

时间:2019-01-22 06:06:23

标签: reactjs

父组件:

    import React from 'react';
    import './Api.scss';
    import ProfileCard from 'components/Card/ProfileCard.jsx';
    import Modal from 'react-awesome-modal';
    // import Search from 'components/Search/Search';

    class Api extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                title : '',
                content: '',
                img: '',
                data: [],
                pages: 0,
                page:0

            }
        }

        OnFileChange = (event) => {
            this.setState({img: event.target.files[0]});
        }

        onTitleChange = (event) => {
            this.setState({title: event.target.value})
        }

        onContentChange = (event) => {
            this.setState({content: event.target.value})
        }

        resetForm = () => {
            document.getElementById('title').value = '';
            document.getElementById('content').value = '';
            document.getElementById('img').value = '';
        }

        openModal() {
            this.setState({
                visible : true
            });
        }

        closeModal() {
            this.setState({
                visible : false
            });
        } 


        componentDidMount() {
            fetch(`http://127.0.0.1:8000/get_profile/?page=${this.state.page}`)
              .then(response => response.json())
              .then(res =>{
                this.setState({ data: res });  
                this.setState({ pages: res[res.length-1].pages });
                console.log(this.state.page)   
            });
          }


        SubmitProfile = (event) => {
            let formData = new FormData();
            formData.append('img',this.state.img);
            formData.append('title',this.state.title);
            formData.append('content',this.state.content);
            fetch('http://127.0.0.1:8000/post_profile/', {
                method: 'post',
                headers: {
                    Accept: 'application/json, text/plain, */*'
                  },
                  body:formData,
              })
              .then(response => response.json())
              .then(res => {
                  if (res.code === 200){
                    this.componentDidMount()
                    this.resetForm()
                    this.closeModal()
                  }
                  console.log(res);
              })
        }


        elasticSearch = (event) => {
            fetch('http://127.0.0.1:8000/search/', {
                method: 'post',
                headers:{'Content-Type': 'application/json'},
                body: JSON.stringify({
                    q: event.target.value 
                })
        })
        .then(response => response.json())
        .then(res => {
            console.log(res)
            this.setState({ data: res })
        });  
        }





        render(){
            return (
                <div className="api-body">
                    <section>
                        <div className="tc pa2">
                            <input
                                type="button"
                                className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                                value="Post"
                                onClick={() => this.openModal()} 
                            />
                            <input
                                className="db ma3 q center border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="q"
                                id="q"
                                onChange = {this.elasticSearch}
                            />
                            </div>
                            <Modal 
                                visible={this.state.visible}
                                width="400"
                                height="300"
                                effect="fadeInDown"
                                onClickAway={() => this.closeModal()}
                            >
                            <div className="mv3 pa3">

                            <label className="db fw6 lh-copy f6" htmlFor="password">Title</label>
                            <input
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="title"
                                id="title"
                                onChange={this.onTitleChange}
                            />
                        </div>
                        <div className="mv3 pa3 mt-1">
                            <label htmlFor="comment" className="f6 b db mb2">Contents </label>
                            <textarea 
                                id="content" 
                                name="content" 
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2" 
                                aria-describedby="content-desc"
                                onChange={this.onContentChange}>
                            </textarea>
                        </div>
                        <div className="mv3 pa3 mt-1">
                        <input
                            type="file"
                            multiple = {false}
                            id="img"
                            name="img"
                            ref={(input) => { this.inpuElement = input; }}
                            accept=".jpg,.jpeg,.png,.pdf,.doc"
                            onChange={this.OnFileChange}
                            />
                        <input
                            type="button"
                            className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                            value="Submit"
                            onClick={this.SubmitProfile} 
                            />
                        </div>
                        </Modal>
                    </section>

                   <ProfileCard 
                    data={this.state.data}
                    pages={this.state.pages}
                    page={this.state.page}
                    />
                </div>
            )
        }
    }


    export default Api;

子组件:

    import React from 'react';


    class ProfileCard extends React.Component {
      constructor(props){
        super(props)
        this.state = {
          data : []
        }
      }

      deleteProfile = id => e => {
        fetch('http://127.0.0.1:8000/delete_profile/', {
          method: 'post',
          headers:{'Content-Type': 'application/json'},
          body: JSON.stringify({
            id: id
          })
        })
        .then(response => response.json())
        .then(res => {
            if (res.code === 200){
              this.componentDidMount()
            }
            console.log(res)
        })
      } 

      demoMethod(page){
        this.props.page(page)
        console.log(page)
      }

      render(){
      return (
        <div>
          {
          this.props.data.map((user,i) => {
            return (
              <article className='mw5 tc bg-white dib br3 pa3 ma3 pa4-ns mv3 ba b--black-10 shadow-5 pc-scroll pointer' key={i}>
              <div className="tc">

               <img 
                  src={"http://127.0.0.1:8000" + user.photo}
                  className="br-100 h3 w3 dib" 
                  alt="profile pic"
                  onDoubleClick = {this.deleteProfile(user.id)}
              />
                 <h1 className="f4">{user.title}</h1>
                 <hr className="mw3 bb bw1 b--black-10" />
               </div>
               <p className="lh-copy measure center f6 black-70">
               {user.content}
               </p>
             </article>
            );
          })
        }

          <div className="pagination">
            <center>
                {[...Array(this.props.pages+1)].map((x, i) =>
                  <h2 key={i} onClick={()=>this.demoMethod(i+1)} className="tc">{ i+1 }</h2>
                )}
            </center>
          </div>

        </div>
      );
      }
    }


    export default ProfileCard;

我想将数据从子组件发送到父组件。 在子组件中,我想从该方法中获得一个 demoMethod(),我想将页面数据发送到父组件的构造函数(状态)。

这样,它不起作用。 并且显示 this.props.page(page)不是功能

请看看这个。

4 个答案:

答案 0 :(得分:1)

您没有将page属性作为函数传递,它应该是函数而不是变量,page是数字状态。您应该发送:

someFunction = () => {
 console.log('function passed from parent')
}
// in render function
<ProfileCard 
      data={this.state.data}
      pages={this.state.pages}
     page={this.someFunction}
/>

答案 1 :(得分:1)

parent中的

page不是函数,而是在构造函数状态中定义的数字变量,因此在Api组件中定义一个新方法,并将该方法作为prop传递给ProfileCard组件,然后在ProfileCard组件demoMethod中调用this.props.getPage(page) ;

这就是所谓的回调。要在父级组件中获取子级数据,函数是唯一一个将数据从子级发送到父级的回调函数

父项

import React from 'react';
import './Api.scss';
import ProfileCard from 'components/Card/ProfileCard.jsx';
import Modal from 'react-awesome-modal';
// import Search from 'components/Search/Search';

class Api extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            title : '',
            content: '',
            img: '',
            data: [],
            pages: 0,
            page:0

        }
    }

    OnFileChange = (event) => {
        this.setState({img: event.target.files[0]});
    }

    onTitleChange = (event) => {
        this.setState({title: event.target.value})
    }

    onContentChange = (event) => {
        this.setState({content: event.target.value})
    }

    resetForm = () => {
        document.getElementById('title').value = '';
        document.getElementById('content').value = '';
        document.getElementById('img').value = '';
    }

    openModal() {
        this.setState({
            visible : true
        });
    }

    closeModal() {
        this.setState({
            visible : false
        });
    } 


    componentDidMount() {
        fetch(`http://127.0.0.1:8000/get_profile/?page=${this.state.page}`)
          .then(response => response.json())
          .then(res =>{
            this.setState({ data: res });  
            this.setState({ pages: res[res.length-1].pages });
            console.log(this.state.page)   
        });
      }


    SubmitProfile = (event) => {
        let formData = new FormData();
        formData.append('img',this.state.img);
        formData.append('title',this.state.title);
        formData.append('content',this.state.content);
        fetch('http://127.0.0.1:8000/post_profile/', {
            method: 'post',
            headers: {
                Accept: 'application/json, text/plain, */*'
              },
              body:formData,
          })
          .then(response => response.json())
          .then(res => {
              if (res.code === 200){
                this.componentDidMount()
                this.resetForm()
                this.closeModal()
              }
              console.log(res);
          })
    }


    elasticSearch = (event) => {
        fetch('http://127.0.0.1:8000/search/', {
            method: 'post',
            headers:{'Content-Type': 'application/json'},
            body: JSON.stringify({
                q: event.target.value 
            })
    })
    .then(response => response.json())
    .then(res => {
        console.log(res)
        this.setState({ data: res })
    });  
    }

   getPage = page => {
      console.log("page from child component:", page);
   }




    render(){
        return (
            <div className="api-body">
                <section>
                    <div className="tc pa2">
                        <input
                            type="button"
                            className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                            value="Post"
                            onClick={() => this.openModal()} 
                        />
                        <input
                            className="db ma3 q center border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                            type="text"
                            name="q"
                            id="q"
                            onChange = {this.elasticSearch}
                        />
                        </div>
                        <Modal 
                            visible={this.state.visible}
                            width="400"
                            height="300"
                            effect="fadeInDown"
                            onClickAway={() => this.closeModal()}
                        >
                        <div className="mv3 pa3">

                        <label className="db fw6 lh-copy f6" htmlFor="password">Title</label>
                        <input
                            className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                            type="text"
                            name="title"
                            id="title"
                            onChange={this.onTitleChange}
                        />
                    </div>
                    <div className="mv3 pa3 mt-1">
                        <label htmlFor="comment" className="f6 b db mb2">Contents </label>
                        <textarea 
                            id="content" 
                            name="content" 
                            className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2" 
                            aria-describedby="content-desc"
                            onChange={this.onContentChange}>
                        </textarea>
                    </div>
                    <div className="mv3 pa3 mt-1">
                    <input
                        type="file"
                        multiple = {false}
                        id="img"
                        name="img"
                        ref={(input) => { this.inpuElement = input; }}
                        accept=".jpg,.jpeg,.png,.pdf,.doc"
                        onChange={this.OnFileChange}
                        />
                    <input
                        type="button"
                        className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                        value="Submit"
                        onClick={this.SubmitProfile} 
                        />
                    </div>
                    </Modal>
                </section>

               <ProfileCard 
                data={this.state.data}
                pages={this.state.pages}
                page={this.state.page}
                getPage={this.getPage}
                />
            </div>
        )
    }
}


export default Api;

子组件

import React from 'react';
class ProfileCard extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      data : []
    }
  }

  deleteProfile = id => e => {
    fetch('http://127.0.0.1:8000/delete_profile/', {
      method: 'post',
      headers:{'Content-Type': 'application/json'},
      body: JSON.stringify({
        id: id
      })
    })
    .then(response => response.json())
    .then(res => {
        if (res.code === 200){
          this.componentDidMount()
        }
        console.log(res)
    })
  } 

  demoMethod(page){
    this.props.getPage(page)
    console.log(page)
  }

  render(){
  return (
    <div>
      {
      this.props.data.map((user,i) => {
        return (
          <article className='mw5 tc bg-white dib br3 pa3 ma3 pa4-ns mv3 ba b--black-10 shadow-5 pc-scroll pointer' key={i}>
          <div className="tc">

           <img 
              src={"http://127.0.0.1:8000" + user.photo}
              className="br-100 h3 w3 dib" 
              alt="profile pic"
              onDoubleClick = {this.deleteProfile(user.id)}
          />
             <h1 className="f4">{user.title}</h1>
             <hr className="mw3 bb bw1 b--black-10" />
           </div>
           <p className="lh-copy measure center f6 black-70">
           {user.content}
           </p>
         </article>
        );
      })
    }

      <div className="pagination">
        <center>
            {[...Array(this.props.pages+1)].map((x, i) =>
              <h2 key={i} onClick={()=>this.demoMethod(i+1)} className="tc">{ i+1 }</h2>
            )}
        </center>
      </div>

    </div>
  );
  }
}


export default ProfileCard;

答案 2 :(得分:0)

在这种情况下,您的数据应位于父组件的状态中,并且您应将处理程序向下传递给具有道具,并使用该处理程序更新父组件中的状态

答案 3 :(得分:0)

向您的父组件添加回叫功能-参见以下构造函数

    class Api extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                title : '',
                content: '',
                img: '',
                data: [],
                pages: 0,
                page:0

            }
        }
        **##Add callback function**
        myCallbackfunc(val){
         this.setState({page:val)}
         }

        OnFileChange = (event) => {
            this.setState({img: event.target.files[0]});
        }

        onTitleChange = (event) => {
            this.setState({title: event.target.value})
        }

        onContentChange = (event) => {
            this.setState({content: event.target.value})
        }

        resetForm = () => {
            document.getElementById('title').value = '';
            document.getElementById('content').value = '';
            document.getElementById('img').value = '';
        }

        openModal() {
            this.setState({
                visible : true
            });
        }

        closeModal() {
            this.setState({
                visible : false
            });
        } 


        componentDidMount() {
            fetch(`http://127.0.0.1:8000/get_profile/?page=${this.state.page}`)
              .then(response => response.json())
              .then(res =>{
                this.setState({ data: res });  
                this.setState({ pages: res[res.length-1].pages });
                console.log(this.state.page)   
            });
          }


        SubmitProfile = (event) => {
            let formData = new FormData();
            formData.append('img',this.state.img);
            formData.append('title',this.state.title);
            formData.append('content',this.state.content);
            fetch('http://127.0.0.1:8000/post_profile/', {
                method: 'post',
                headers: {
                    Accept: 'application/json, text/plain, */*'
                  },
                  body:formData,
              })
              .then(response => response.json())
              .then(res => {
                  if (res.code === 200){
                    this.componentDidMount()
                    this.resetForm()
                    this.closeModal()
                  }
                  console.log(res);
              })
        }


        elasticSearch = (event) => {
            fetch('http://127.0.0.1:8000/search/', {
                method: 'post',
                headers:{'Content-Type': 'application/json'},
                body: JSON.stringify({
                    q: event.target.value 
                })
        })
        .then(response => response.json())
        .then(res => {
            console.log(res)
            this.setState({ data: res })
        });  
        }





        render(){
            return (
                <div className="api-body">
                    <section>
                        <div className="tc pa2">
                            <input
                                type="button"
                                className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                                value="Post"
                                onClick={() => this.openModal()} 
                            />
                            <input
                                className="db ma3 q center border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="q"
                                id="q"
                                onChange = {this.elasticSearch}
                            />
                            </div>
                            <Modal 
                                visible={this.state.visible}
                                width="400"
                                height="300"
                                effect="fadeInDown"
                                onClickAway={() => this.closeModal()}
                            >
                            <div className="mv3 pa3">

                            <label className="db fw6 lh-copy f6" htmlFor="password">Title</label>
                            <input
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="title"
                                id="title"
                                onChange={this.onTitleChange}
                            />
                        </div>
                        <div className="mv3 pa3 mt-1">
                            <label htmlFor="comment" className="f6 b db mb2">Contents </label>
                            <textarea 
                                id="content" 
                                name="content" 
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2" 
                                aria-describedby="content-desc"
                                onChange={this.onContentChange}>
                            </textarea>
                        </div>
                        <div className="mv3 pa3 mt-1">
                        <input
                            type="file"
                            multiple = {false}
                            id="img"
                            name="img"
                            ref={(input) => { this.inpuElement = input; }}
                            accept=".jpg,.jpeg,.png,.pdf,.doc"
                            onChange={this.OnFileChange}
                            />
                        <input
                            type="button"
                            className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                            value="Submit"
                            onClick={this.SubmitProfile} 
                            />
                        </div>
                        </Modal>
                    </section>

                   <ProfileCard 
                    data={this.state.data}
                    pages={this.state.pages}
                    page={this.state.page}
#Pass the call back function as a prop to the child component
                    mycallbackfunc = {this.myCallbackfunc)
                    />
                </div>
            )
        }
    }        
    export default Api;

对于您的子组件,在demoMethod函数中添加以下行

demoMethod(page){
Change the below line
this.props.myCallbackfunc(page)
console.log(page)
}