Goal: I am trying to change the link inside the fetch() function with the value that comes from the dropdown.
Attempts:
1) I attempted passing the value to the function like GetAPILinks(Link_from_dropdown)
and calling it in the onSelect function however I am getting an error stating: Invalid hook call. Hooks can only be called inside of the body of a function component
Invalid hook call. Hooks can only be called inside of the body of a function component
2) I have also tried other methods of passing it by storing it in a variable inside GetAPILinks but resulted in errors.
I am starting to believe I am approaching this all wrong. Any advice or help would be great!
My Code:
This code will fetch the data from a hard coded link and renders a dropdown button that prints the selected values to the console.
import React from 'react';
import { DropdownButton, Dropdown} from 'react-bootstrap';
const GetAPILinks = () => {
const [apiData, setApiData] = React.useState([]);
React.useEffect(() => {
fetch('https://Random_API/Link_From_Dropdown_Goes_Here')
.then((response) => {
return response.json();
})
.then((data) => {
setApiData(data);
});
}, []);
return (
<DropdownButton id="dropdown-item-button" title="API Links" onSelect={function(evt){console.log(evt)}}>
<Dropdown.Item as="button" eventKey='API_Link1'>Link 1</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link2'>Link 2</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link3'>Link 3</Dropdown.Item>
</DropdownButton>
);
}
export default GetAPILinks;
You're pretty close here. You should track another state value for the fetch Url. Tracking it in a local variable, or calling the function directly won't trigger your component to render when the values change.
const [fetchUrl, setFetchUrl] = useState(initialValue);
in your onSelect
drop down you can set the value of the fetchUrl
using the setFetchUrl
function that the useState
hook provides.
Now all that is left is to tell your useEffect
hook that it needs to execute whenever the fetchUrl
state value changes. You should add fetchUrl
to the deps array.
It might look something like this:
const GetAPILinks = () => {
const [apiData, setApiData] = React.useState([]);
const [fetchUrl, setFetchUrl] = React.useState('');
React.useEffect(() => {
if (fetchUrl) {
fetch(fetchUrl)
.then((response) => {
return response.json();
})
.then((data) => {
setApiData(data);
});
}
}, [fetchUrl]);
return (
<DropdownButton id="dropdown-item-button" title="API Links" onSelect={(e)=>{setFetchUrl(e.target.eventKey)}}>
<Dropdown.Item as="button" eventKey='API_Link1'>Link 1</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link2'>Link 2</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link3'>Link 3</Dropdown.Item>
</DropdownButton>
);
}
const GetAPILinks = () => {
const [apiData, setApiData] = React.useState([]);
const [url, setUrl] = React.useState(null);
React.useEffect(() => {
if (url) {
fetch('https://${url}`)
.then((response) => {
return response.json();
})
.then((data) => {
setApiData(data);
}});
}, [url]);
return (
<DropdownButton id="dropdown-item-button" title="API Links"
onSelect={evt=>setUrl(evt.key)}>
<Dropdown.Item as="button" eventKey='API_Link1'>Link
1
</Dropdown.Item>
</DropdownButton>
);
}
export default GetAPILinks;
You should create another state for current link and add it to useEffect
dependencies.
It should be something like that, I didn't test.
import React from 'react';
import { DropdownButton, Dropdown} from 'react-bootstrap';
const GetAPILinks = () => {
const [apiData, setApiData] = React.useState([]);
const [currentLink, setCurrentLink] = React.useState('');
React.useEffect(() => {
fetch(`https://Random_API/${currentLink}`)
.then((response) => {
return response.json();
})
.then((data) => {
setApiData(data);
});
}, [currentLink]);
return (
<DropdownButton id="dropdown-item-button" title="API Links" onSelect={(e)=>{setCurrentLink(e.target.eventKey)}}>
<Dropdown.Item as="button" eventKey='API_Link1'>Link 1</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link2'>Link 2</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link3'>Link 3</Dropdown.Item>
</DropdownButton>
);
}
export default GetAPILinks;
Hope it helps.
Add another piece of state to track the selected dropdown value
const [query, setQuery] = useState();
And add query
to the dependency array of the effect and only make the fetch request when query
is truthy
React.useEffect(() => {
query && fetch(`https://Random_API/${query}`)
.then((response) => {
return response.json();
})
.then((data) => {
setApiData(data);
});
}, [query]);
A cleaner solution may be to factor out the fetch logic to its own function, call that with the callback, and store only the result in state
const GetAPILinks = () => {
const [apiData, setApiData] = useState([]);
const fetchData = query => fetch(`https://Random_API/${query}`)
.then((response) => {
return response.json();
})
.then(setApiData(data));
return (
<DropdownButton id="dropdown-item-button" title="API Links" onSelect={fetchData}>
<Dropdown.Item as="button" eventKey='API_Link1'>Link 1</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link2'>Link 2</Dropdown.Item>
<Dropdown.Item as="button" eventKey='API_Link3'>Link 3</Dropdown.Item>
</DropdownButton>
);
}
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.