I am quite new, this is my first question post I was hoping someone else will of had a similar problem.
I am receiving api data and turning into the JSON format. From that I can access the keys & values within an object (each monster)
hit_points: 17 (key: value)
hit_dice: "5d6" (key: value)
speed: {fly: 40, walk: 20} (object)
special_abilities: Array(1)
0:
desc: "some text"
name: "One with Wind"
I am able to access special_abilities[0].name
, in this case i get back "One with Wind"
.
What I cannot work out how to do is when I get more then one ability how to display all 3 without crashing the script when a monster has only 1 ability.
import React, {useState, useEffect} from 'react';
import './App.css';
function currentMonster({match}) {
const [item, setItem] = useState([]);
useEffect (() => {
fetchMonster();
}, []);
const fetchMonster = async () => {
const mob = match.params.id.toLowerCase();
const fetchMonster = await fetch(`https://api.open5e.com/monsters/${mob}/?format=json`)
const monster = await fetchMonster.json();
setItem(monster)
console.log(monster);
// const abilities = monster.special_abilities[0].name
}
return (
<div>
<h1>{item.name}</h1>
<p>Size: {item.size}</p>
<p>Race: {item.type}</p>
<p>Alignment: {item.alignment}</p>
<p>Armor Class: {item.armor_class}</p>
<p>Hit points: {item.hit_points}</p>
<p>Hit dice: {item.hit_dice}</p>
<p>Strength: {item.strength}</p>
<p>Dexterity: {item.dexterity}</p>
<p>Constitution: {item.constitution}</p>
<p>Intelligence: {item.intelligence}</p>
<p>Wisdom: {item.wisdom}</p>
<p>Charisma: {item.charisma}</p>
<p>Senses: {item.senses}</p>
<p>CR: {item.challenge_rating}</p>
</div>
)
}
export default currentMonster;
This is the code I have currently, I wish to add another <p></p>
on the list displaying each special ability and desc of the monsters, and when they have more then one ability those also.
Before asking I have tried to:
const [ability, setAbility] = useState([]);
setAbility(monster.special_abilities[0])
and then <p>{ability.name}</p>
while this works for one monster, if the monster has more then one ability I cannot see them. If the monster has less then two abilities and I log say [0][1][2]
the website crashes.
I hope someone can help me with this while questions similar to this have been asked before in stack overflow I have not been able to find inspiration or an answer.
Kind regards,
Sheep
Here is an example of how to fetch monster when current
changes, you can get current
from match.params.id
but I don't want to make a routed example to demonstrate. Note that I am using monster.slug, this may not be the same as monster name. You should use monster.slug as well because that's what the api uses.
Make sure that current is a dependency of your effect so it'll re run when it changes. I don't think you have your development environment set up correctly because the code you are showing has missing dependencies and your editor should have warned you
const { useState, useEffect } = React;
const App = () => {
const [current, setCurrent] = useState('aatxe');
//you can do:
//const current = match.params.id.toLowerCase();
const [item, setItem] = useState(null);
useEffect(() => {
//SO code snippet doesn't have recent babel, so no
// async await support in snippet code, changed to
// promise
const fetchMonster = () =>
fetch(
`https://api.open5e.com/monsters/${current}/?format=json`
)
.then(response => response.json())
.then(setItem);
fetchMonster();
}, [current]);
return (
<div>
<select
value={current}
onChange={e => setCurrent(e.target.value)}
>
<option value="aatxe">Aatxe</option>
<option value="aboleth">Aboleth</option>
</select>
{item && (
<div>
<h1>{item.name}</h1>
<ul>
{item.special_abilities.map(
(ability, index) => (
<li key={index}>{ability.name}</li>
)
)}
</ul>
</div>
)}
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments