reactjs - 在reactjs中,如何将子组件中的数据发送到父组件状态

  显示原文与译文双语对照的内容
89 5

父组件:

 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;

我想从子组件向父组件发送数据。在子组件中,我从该方法向父组件 constructor(state) 发送页面数据1 英镑的demoMethod() 表。

这样就不工作了。显示 this.props.page(page) 不是一个函数

请看看这个。

时间:原作者:0个回答

132 0

你没有将 page prop作为函数传递,它应该是函数,而不是变量,page 是状态中的数字。你应该发送:

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

父对象的页面不是函数,而是在构造函数状态定义的数字变量,因此定义了Api组件的新方法,并将方法传递给了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;
原作者:
68 2

这种情况下,数据 reside components state state passing passing passing handler handler props props props子组件 update props props 。

原作者:
...