父组件:
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)不是功能
请看看这个。
答案 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)
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)
}