Reputation: 806
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
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
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
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
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