简体   繁体   中英

Reactjs How to right pass arguments to function in props

I studying The Odin Project and try to code CV app ( https://www.theodinproject.com/paths/full-stack-javascript/courses/javascript/lessons/cv-application ). I complete Bio part (name, phone, email). I understand that Job experince and Education components mostly the same. So i try to code Job experience component. In my App component i declare method to add another job (addJob method), and method to update state of App according to data in Job component with right id. To update this data in app i specified unique id to each job component. What is the best practise to code handleJobChange method?

I try to send data to my parent component from child.

App Component

import React from 'react';
import Bio from './components/Bio'
import CV from './components/CV'
import Job from './components/Job'

class App extends React.Component {
  constructor() {
    super()

    this.handleBioChange = this.handleBioChange.bind(this)
    this.idGen = this.idGen.bind(this)
    this.handleJobChange = this.handleJobChange.bind(this)

    this.state = {
      bio_state: {name:'', phone:'', email:''},
      job: [{id:this.idGen(), company:'', position:'',tasks:'', start:'', until:''}]

    }
  }
  
  idGen() {
     return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
  }

  handleBioChange = (e) => {
    this.setState({
      bio_state: Object.assign(this.state.bio_state,{[e.target.name]: e.target.value})
    })
  }

  addJob = () => {
    this.setState(this.state.job.concat([
      {id:this.idGen(), company:'', position:'',tasks:'', start:'', until:''}
    ]))
  }

  handleJobChange = (e, id) => {
    this.setState(previousState => {
      console.log(e.target)
      console.log("id is ",id)
      let job = [...previousState.job]
      console.log(job)
      let indexOfJob = job.findIndex(job => job.id === id)
      console.log(indexOfJob)
      job[indexOfJob] = {...job[indexOfJob], [e.target.name]: e.target.value}
      return { job }
    })
  }

  render() {
    console.log('app state', this.state.bio_state)
    return (
      <div>
        <Bio onBioChange={this.handleBioChange} />
        {
            this.state.job.map((item) => (
                <Job id={item.id} onJobChange={this.handleJobChange}/>
            ))
        }
        <CV name={this.state.bio_state.name} phone={this.state.bio_state.phone} email={this.state.bio_state.email} jobs={this.state.job}/>
      </div>
    )
  }
}

child component

import React from 'react'

class Job extends React.Component{
  constructor(props){
    super(props)
  }

  render(){
    const id = this.props.id
    return(
      <div id={this.props.id}>
        <label for='company'>Company:</label>
        <input name='company' onChange={(id=this.props.id)=>this.props.onJobChange(id)}></input>
        
        <label for='position'>Position:</label>
        <input name='position' onChange={()=>this.props.onJobChange(id)}></input>
        
        <label for='tasks'>Tasks:</label>
        <input name='tasks' onChange={()=>this.props.onJobChange(this.props.id)}></input>
        
        <label for='start'>Date from:</label>
        <input name='start' onChange={()=>this.props.onJobChange(this.props.id)}></input>
        
        <label for='until'>Date until:</label>
        <input name='until' onChange={()=>this.props.onJobChange(this.props.id)}></input>
      </div>
    )
  }
}

export default Job

I dont know what to do, seems like I incorrect use function in my child component with parameters. Please help? I'am desperate =(

I figure it out. I change my app component handleJobChange method like so

handleJobChange = (id, key,value) => {
    this.setState(previousState => {
      console.log("id is ", id)
      console.log("key is ", key)
      console.log("val is ", value)
      let job = [...previousState.job]
      console.log(job)
      let indexOfJob = job.findIndex(job => job.id === id)
      console.log(indexOfJob)
      job[indexOfJob] = {...job[indexOfJob], [key]: value}
      return { job }
    })
  }

And in my Job component i change like so

class Job extends React.Component{
  constructor(props){
    super(props)
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange=(e)=>{
    const key = e.target.name
    const value = e.target.value
    const id = this.props.id

    this.props.onJobChange(id, key, value)
  }

  render(){
    const id = this.props.id
    return(
      <div id={this.props.id}>
        <label for='company'>Company:</label>
        <input name='company' onChange={this.handleChange}></input>
        
        <label for='position'>Position:</label>
        <input name='position' onChange={this.handleChange}></input>
        
        <label for='tasks'>Tasks:</label>
        <input name='tasks' onChange={this.handleChange}></input>
        
        <label for='start'>Date from:</label>
        <input name='start' onChange={this.handleChange}></input>
        
        <label for='until'>Date until:</label>
        <input name='until' onChange={this.handleChange}></input>
      </div>
    )
  }
}

And its worked !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM