i have a useEffect
on the parent component that runs a fetch call on render
useEffect(() => {
const fetchCall = async () => {
try{
const res = await fetch('https://www.dnd5eapi.co/api/races')
const data = await res.json()
setFetchData(prevData => ({
...prevData,
race_list:data.results
}))
// console.log('been fetched')
}catch(err){
console.error('Error fetching data: ', err)
}
}
fetchCall()
})
then the parent uses an if else
statement to determine the content of a div and it looks like this
const decideDiv = (e, divType) => {
if(divType === 'div_1'){
return (
<div>
<div id='race'>
<Race functions={{setFetchData:setFetchData,
raceFetch: raceFetch,
fetchData:fetchData}} />
</div>
</div>
)
}
}
if i log fetchData
to the console in the parent div it logs everything correctly. if i log it in the child component it only renders the initial state.
the parent component
export default function CharCreator () {
const [fetchData, setFetchData] = useState(...someObj)
useEffect(() => {
const fetchCall = async () => {
try{
const res = await fetch('https://www.dnd5eapi.co/api/races')
const data = await res.json()
setFetchData(prevData => ({
...prevData,
race_list:data.results
}))
// console.log('been fetched')
}catch(err){
console.error('Error fetching data: ', err)
}
}
fetchCall()
})
// INITIAL STATE OF THE DIV
const [div, setDiv] = useState(
<div>
<button onClick={(e) => {handleNewChar(e, 'class/race')}}>Create Character</button>
</div>
)
const handleNewChar = (e, newDiv) => {
e.preventDefault()
// setCount(prevCount => prevCount + 1)
if(newDiv === 'class/race'){
setDiv(
<div>
<div id='race_class'>
<div id='race'>
<Race functions={{setFetchData:setFetchData,
raceFetch: raceFetch,
fetchData:fetchData}} />
</div>
</div>
}else if(other logic for other components){
...other compoents being rendered
}
}
return(
<div id='outerParent'>
<form>
{div}
<p>
<button onClick={logs}>fetchData</button>
</p>
</form>
</div>
)
}
the child component
export default function Race({functions}) {
const {fetchData, raceFetch, setFetchData} = functions
const [div, setDiv] = useState()
const isHidden = fetchData?.race?.name ? '' : 'none'
useEffect(() => {
const fetchCall = async () => {
try{
const res = await fetch('https://www.dnd5eapi.co/api/races')
const data = await res.json()
setFetchData(prevData => ({
...prevData,
race_list:data.results
}))
}catch(err){
console.error('Error fetching data: ', err)
}
}
fetchCall()
})
//ONLY SHOWS THE INITIAL STATE
console.log('race list', fetchData?.race_list)
useEffect(() => {
setDiv(
<>
<p>
<select onChange={verifyInput} id='raceSet' defaultValue=''>
<option value='' disabled >Select a Race</option>
{fetchData?.race_list?.map((race, i) => (
<option
key={i}
data-url={race.url}
value={race.name}>
{race.name}
</option>
))}
</select>
</p>
</>
)
}, [fetchData?.race_list])
const verifyInput = (e) => {
const input = e.target.value
const selected = e.target.options[e.target.selectedIndex]
const url = selected.getAttribute('data-url')
console.log('url', url)
const compare = fetchData?.race_list?.some(element => element.name === input) || fetchData?.race_list?.some(element => element.name.toLowerCase() === input)
raceFetch(url)
setSpawn(prevSpawn => prevSpawn + 1)
}
return(
<div>
<div>
<h2>Race</h2>
</div>
{div}
<div>
{spawn > 0 ?
<div id='raceInfo'>
<RaceInfo functions={{fetchData:fetchData,
setFetchData:setFetchData}} />
</div>
:''}
</div>
</div>
)
}
there is no ‘too many requests’ error either
it worked fine when i just all the divs render at the same time, but now that i have it set to only render one at a time it seems that the new state of fetchData
is not being sent to the child. i tried moving the fetch call to the child component, but that didnt work either and it still only logs the initial state of fetchData
.
4