I can not seem to get props working for passing information from my child class up to my parent class. What I am trying to do, is to detect what dropdown menu option someone has chosen, send that information up to the parent class which then takes the chosen option and runs a call to backend that then returns a list of database items which match the chosen option.
Below is the child class:
import React,{useState} from 'react';
import SEPractices from "../dummydata/SEPractices"
const optionItems = SEPractices.map((SEPractice) =>
<option key={SEPractice.practice}>{SEPractice.practice}</option>
);
const Dropdown = () => {
const [selectValue, setValue] = useState("")
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
this.props.handlePractice(e.target.value);
}
return (
<div>
<select value={selectValue} onChange={handleSelect}>
<option value="dummyData">
Select an SE Practice
</option>
{optionItems}
</select>
</div>
)
}
export default Dropdown;
Below is the parent class:
import React,{useState} from "react";
import Styles from "../components/tablestyle.js";
import Table from "../components/evidencetable.js";
import tablecolumns from "../components/tablecolumns.js";
import Dropdown from "../components/Dropdown.js";
import axios from "axios";
//const dbArticles = [];
class SEPractice extends React.Component{
/*constructor(props){
this.state = {dbArticles: []};
this.componentDidMount = this.componentDidMount.bind(this);
this.getArticles = this.getArticles.bind(this);
this.practice = this.practice.bind(this);
}*/
state={
dbArticles: []
}
handlePractice (Option) {
console.log("hi");
// axios.get(`https://protected-plains-77403.herokuapp.com/api/articles/${Option}`)
axios.get(`https://localhost:5000/api/articles/${Option}`)
.then((response) =>{
const data = response.data;
this.setState({dbArticles: data});
console.log('state', this.state);
})
.catch(()=>{
alert('error retrieving data');
});
}
componentDidMount = () =>{
this.getArticles();
}
getArticles = () =>{
axios.get('https://protected-plains-77403.herokuapp.com/api/articles')
.then((response) =>{
const data = response.data;
this.setState({dbArticles: data});
console.log('state', this.state);
})
.catch(()=>{
alert('error retrieving data');
});
}
/*practice =() =>{
const [selected, setSelected] = useState('');
const practiceHandler = (e) =>{
setSelected(e);
}
}*/
render() {
return (
<div>
<h2>Select SE Practice to get evidence for the claimed benefits</h2>
<Dropdown onDropdown={this.handlePractice}/>
<Styles>
<Table
data={this.state.dbArticles}
columns={tablecolumns}
/>
</Styles>
</div>
);
}
}
export default SEPractice;
I followed a few articles and stack overflow blogs and they all say to do this.props.method which I did:
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
this.props.handlePractice(e.target.value);
}
CodePudding user response:
In the parent class, you are not correctly binding the method in the constructor. You need the following:
class SEPractice extends React.Component {
constructor(props) {
super(props);
this.state = {
dbArticles: []
}
this.handlePractice = this.handlePractice.bind(this);
}
The handlePractice
method is now bound to the parent component. When you pass it to the child component, you assign it to the property onDropdown
. You need to then access it correctly from the child component using the onDropdown
property to which you have assigned it. Note, because the child component is a functional component, we do not use this.props
, like you did in the parent component which is a class component. Like so:
const Dropdown = (props) => {
const [selectValue, setValue] = useState("")
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
props.onDropdown(e.target.value); //Not this.props
}
return (
<div>
<select value={selectValue} onChange={handleSelect}>
<option value="dummyData">
Select an SE Practice
</option>
{optionItems}
</select>
</div>
)
}
export default Dropdown;
}
CodePudding user response:
you need to change your code to
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
this.props.onDropdown(e.target.value);
}
The reason is because on the dropdown component you named the prop onDropdown
When you are trying to console.log your state after doing setState
do it like so
const data = response.data;
this.setState({dbArticles: data},() => console.log('state', this.state));
})
the reason is that setState is asynchronous and the second argument is a callback that fires after state has actually been set.
CodePudding user response:
You are not receiving any props in the component as you are not allowing for the parameter and also acting on the incorrect prop name:
const Dropdown = () => { // missing props here
const [selectValue, setValue] = useState("")
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
this.props.handlePractice(e.target.value); // problem here
}
return (
<div>
<select value={selectValue} onChange={handleSelect}>
<option value="dummyData">
Select an SE Practice
</option>
{optionItems}
</select>
</div>
)
}
export default Dropdown;
Update to receive the props:
const Dropdown = (props) => {
const [selectValue, setValue] = useState("")
const handleSelect = (e) => {
console.log(e.target.value);
setValue(e.target.value);
props.onDropdown(e.target.value); // note correct name
}
return (
<div>
<select value={selectValue} onChange={handleSelect}>
<option value="dummyData">
Select an SE Practice
</option>
{optionItems}
</select>
</div>
)
}
export default Dropdown;