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,