soubhagya
soubhagya

Reputation: 806

how to send data from child component to parent component state in reactjs

parent component:

    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;

child component:

    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;

I wants to send data from child to parent component. in child component i have one demoMethod() from that method i wants to send page data to parent component constructor(state).

This way it is not working. And showing this.props.page(page) is not a function

Please have a look into this.

Upvotes: 0

Views: 109

Answers (4)

mastershefi
mastershefi

Reputation: 153

Add a call Back function to your parent component - See below constructor

    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;

To your child component, in the demoMethod function add this line

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

Upvotes: 0

Hemadri Dasari
Hemadri Dasari

Reputation: 33994

page in parent is not a function but a number variable defined in constructor state so define a new method in Api component and pass down the method to ProfileCard component as prop and in ProfileCard component demoMethod call this.props.getPage(page);

This is so called callbacks in react. To get child data in parent component a function is the only callback that sends data from child to parent

Parent component

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;

Child Component

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;

Upvotes: 1

Umair Farooq
Umair Farooq

Reputation: 1823

You are not passing page prop as function, it should be a function instead of variable, page is number in state. You should send:

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

Upvotes: 1

Praveen Rao Chavan.G
Praveen Rao Chavan.G

Reputation: 2860

In this case, your data should reside in parent components state and you should be passing a handler down to child component has props and use that handler to update the state in parent component.

Upvotes: 0

Related Questions