Home > OS >  How to pass data from Component to form submit in ReactJS?
How to pass data from Component to form submit in ReactJS?

Time:11-17

I have created Dropdown which extends Component. In this I am fetching muliple dropdown values an storing it in const data. I want pass this data from Dropdown Component to another Component in the form of function. Any help would be really great as I am new to React and facing bit challenge.

export class CascadingDropdown extends Component {
    constructor(props) {
        super(props)
        this.state = {
            ...
            dropdown_data: []
        }
    }

    componentDidMount() {
        axios.get('/api/fetchCategory').then(response => {
        this.setState({
            CategoryData: response.data
        });
    });
 }

    ChangeSubCategory = (e) => {
        this.setState({
            category_id: e.target.value
        });
        axios.get('/api/fetchSubCategory?category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
                SubCategoryData: response.data,
            });
        });
    }

    ChangeSubject = (e) => {
        this.setState({
            sub_category_id: e.target.value
        });
        
        axios.get('/api/fetchSubjects?sub_category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
                subject: response.data
            });
        });
    }   

    storeData = (e) => {
        this.setState({
            subject_id: e.target.value
        });
    }    

    render() {       

        const dropdown_data = {
            category_id: this.state.category_id,
            sub_category_id: this.state.sub_category_id,
            subject_id: this.state.subject_id
        }

        console.log(dropdown_data)

        return (  
            <div className ="row">  
                . . .        
            </div>
        )
    }  
}  

export default CascadingDropdown

The value from dropdown_data should be passed to a function and below is the code that I have tried.

function CreateTicket() {
    const [ticketInput, setTicketInput] = useState({           
       category_id: '',
       sub_category_id: '',
       subject_id: '',
       other_subject: '',
       file: '',
       auto_message: '',
    });
    
    const handleTicketInput = (e) => {
       e.persist();
        setTicketInput({...ticketInput, [e.target.name]: e.target.value })
    }
    
      const submitTicket = (e) => {
         e.preventDefault();
          const data = {
                ...
         }
       axios.post(`/api/store-ticket`, data).then(res => {
         console.log(res.data);
             . . .
            })
        }
    
      return (
        <div className ="container"> 
        <form onSubmit ={handleSubmit}>
             <input id="emp_name" type="text" name="employee_name" className ="form-control" disabled = "disabled" onChange = {handleTicketInput} value = {empname} />
             <CascadingDropdown />
             <input id="form_other_subject" type="text" name="other_subject" disabled = "disabled" className ="form-control" value = {ticketInput.other_subject} onChange = {handleTicketInput} /> 
        
            </form>
          </div>
        )
        }
        export default CreateTicket;

CodePudding user response:

This is what i can do for nested state, and update states, i have used single json object dropdown_data and passed down to children, its getting complex to update state of it but easy to prop down the children,
Soution 1 (OLD):

export class CascadingDropdown extends Component {
    constructor(props) {
        super(props)
        this.state = {
            dropdown_data: {
              subject_id, category_id, sub_category_id
            },
            CategoryData,
            SubCategoryData,
            subject
        }
    }
    this.ChangeSubCategory = this.ChangeSubCategory.bind(this);
    this.ChangeSubject = this.ChangeSubject.bind(this);
    this.storeData = this.storeData.bind(this);

    componentDidMount() {
        axios.get('/api/fetchCategory').then(response => {
        this.setState({
            ...this.state,
            CategoryData: response.data
        });
    });
}

    ChangeSubCategory = (e) => {
        this.setState({
            ...this.state,
            dropdown_data: {
              ...this.state.dropdown_data,
              category_id: e.target.value
            }
        });
        axios.get('/api/fetchSubCategory?category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
              ...this.state,
                SubCategoryData: response.data,
            });
        });
    }

    ChangeSubject = (e) => {
        this.setState({
          ...this.state,
          dropdown_data: {
            ...this.state.dropdown_data,
            sub_category_id: e.target.value
          }
        });
        
        axios.get('/api/fetchSubjects?sub_category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
              ...this.state,
                subject: response.data
            });
        });
    }   

    storeData = (e) => {
        this.setState({
          ...this.state,
          dropdown_data: {
            ...this.state.dropdown_data,
            subject_id: e.target.value
          } 
        });
    }    

    render() {       
        console.log(this.state.dropdown_data)

        return (  
            <div className ="row">  
                <CreateTicket dropdown_data={this.state.dropdown_data}/>    
            </div>
        )
    }  
}  

export default CascadingDropdown

you can even pass function callbacks too,

<CreateTicket dropdown_data={this.state.dropdown_data} ChangeSubCategory={ChangeSubCategory} ChangeSubject={ChangeSubject} storeData={storeData}/

this is how you can get your parent state down into functional componenet

function CreateTicket(props) {

  const [dropdown_data, setDropdown_data] = useState(props.dropdown_data); // use hooks now
  //const dropdown_data = this.props.dropdown_data;

}

my new edited answer as per your new question is as follows,
Soution 2 (NEW):

export class CascadingDropdown extends Component {
    constructor(props) {
        super(props)
        this.state = {
            dropdown_data: {
              subject_id:this.props.subject_id, category_id:this.props.category_id, sub_category_id:this.props.sub_category_id
            },
            CategoryData,
            SubCategoryData,
            subject
        }
    }
    // this.ChangeSubCategory = this.ChangeSubCategory.bind(this);
    // this.ChangeSubject = this.ChangeSubject.bind(this);
    // this.storeData = this.storeData.bind(this);

    componentDidMount() {
        axios.get('/api/fetchCategory').then(response => {
        this.setState({
            ...this.state,
            CategoryData: response.data
        });
    });
}

    ChangeSubCategory = (e) => {
      this.props.ChangeSubCategory(e.target.value)
        this.setState({
            ...this.state,
            dropdown_data: {
              ...this.state.dropdown_data,
              category_id: e.target.value
            }
        });
        axios.get('/api/fetchSubCategory?category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
              ...this.state,
                SubCategoryData: response.data,
            });
        });
    }

    ChangeSubject = (e) => {
      this.props.ChangeSubject(e.target.value);
        this.setState({
          ...this.state,
          dropdown_data: {
            ...this.state.dropdown_data,
            sub_category_id: e.target.value
          }
        });
        
        axios.get('/api/fetchSubjects?sub_category_id='   e.target.value).then(response => {
            // console.log(response.data);
            this.setState({
              ...this.state,
                subject: response.data
            });
        });
    }   

    storeData = (e) => {
      this.props.storeData(e.target.value);
        this.setState({
          ...this.state,
          dropdown_data: {
            ...this.state.dropdown_data,
            subject_id: e.target.value
          } 
        });
    }    

    render() {       
        console.log(this.state.dropdown_data)

        return (  
            <div className ="row">  
                <CreateTicket />    
            </div>
        )
    }  
}  

export default CascadingDropdown

and its parent function is,

function CreateTicket(props) {

  const [dropdown_data, setDropdown_data] = useState({
    subject_id:"", category_id:"", sub_category_id:""
  }); // use hooks now

  ChangeSubCategory=(category_id)=>{
    setDropdown_data({...dropdown_data,category_id})
  }
  ChangeSubject=(sub_category_id)=>{
    setDropdown_data({...dropdown_data,sub_category_id})
  }
  storeData=(subject_id)=>{
    setDropdown_data({...dropdown_data,subject_id})
  }

  return (
    <div className ="container"> 
    <form onSubmit ={handleSubmit}>
         <input id="emp_name" type="text" name="employee_name" className ="form-control" disabled = "disabled" onChange = {handleTicketInput} value = {empname} />
            <CascadingDropdown dropdown_data={dropdown_data} ChangeSubCategory={ChangeSubCategory} ChangeSubject={ChangeSubject} storeData={storeData}/>
         <input id="form_other_subject" type="text" name="other_subject" disabled = "disabled" className ="form-control" value = {ticketInput.other_subject} onChange = {handleTicketInput} />
        </form>
      </div>
    )

}

i hope this will work now,

  • Related