经过数小时的尝试纠正代码后,我来这里寻求帮助。 这个想法是寻找一个角色,并显示一些我选择的细节,现在 我根本无法解决这个问题,因为我尝试对死亡数组进行迭代并从那里收集一些信息:
我正在使用以下API:https://tibiadata.com/doc-api-v2/characters/
import React ,{useEffect,useState}from 'react'
import './App.css';
import SearchCharacter from './SearchCharacter'
import Death from './Death'
function App() {
const [currentPlayer,setCurrentPlayer] =useState([])
const [playerDeath,setPlayerDeath] =useState([])
const [search,setSearch] = useState("")
const [query,setQuery] = useState('')
const BASE_URL = `https://api.tibiadata.com/v2/characters/${query}.json`
useEffect(() => {
fetch(BASE_URL)
.then(res =>res.json())
.then(data=>{
setCurrentPlayer(data.characters.data,...Object.keys(data.characters.data))
setPlayerDeath(...data.characters.deaths,...Object.keys(data.characters.deaths))
})
}, [query])
const updateSearch = e=>{
setSearch(e.target.value)
}
const getSearch =e =>{
e.preventDefault();
setQuery(search)
setSearch('')
}
return (
<div>
<h1>Tibia </h1>
<form onSubmit ={getSearch}>
<input placeholder="Enter Name" input ={search} onChange ={updateSearch}/>
<button >Search</button>
</form>
<SearchCharacter currentPlayer ={currentPlayer}/>
{playerDeath.map(death =>(<Death
key = {death.death.reason}
reason = {death.death.reason}
level = {death.death.level}
/>))}
</div>
)
}
export default App
死亡组件:
import React from 'react'
const Death =({reason,level}) =>{
return (
<div>
<p>Player Death: Played died by {reason} at level : {level}</p>
</div>
)
}
export default Death;
搜索字符组件:
import React from 'react'
const SearchCharacter =({currentPlayer}) =>{
return (
<div>
<p>Player Name :{currentPlayer.name}</p>
<p>Player Level :{currentPlayer.level}</p>
<p>Player Vocation :{currentPlayer.vocation}</p>
</div>
)
}
export default SearchCharacter
我基本上想做的是在“玩家死亡”下显示角色的所有死亡,但是无论我尝试的代码如何变化,我都会不断遇到相同的错误:
data.map不是函数-我曾尝试将其他解决方案改编成我的代码,但我无法使其正常工作。 在某个时候,我可以证明有一个死亡,如果没有死亡,代码将崩溃。
现在,在大量使用我的代码之后,它甚至都不会显示Death组件jsx。
任何帮助将不胜感激!
答案 0 :(得分:2)
更改setPlayerDeath(...data.characters.deaths,...Object.keys(data.characters.deaths))
到setPlayerDeath([...data.characters.deaths,...Object.keys(data.characters.deaths)])
当您想要setPlayerDeath(v1, v2, v3, v4, ...etc)
时,您实际上正在做setPlayerDeath([v1, v2, v3, v4, ...etc])
答案 1 :(得分:0)
import React from 'react'
import ReactDOM from 'react-dom'
import ReactBootstrap from 'react-bootstrap'
import { ListGroup } from 'react-bootstrap'
import { ListGroupItem } from 'react-bootstrap'
import { Panel } from 'react-bootstrap'
import { ButtonGroup } from 'react-bootstrap'
import { Button } from 'react-bootstrap'
import { Modal } from 'react-bootstrap'
const recipes = [
{
"name" : "Baklava",
"ingredients": ["Flower", "Baking soda", "Pistachios", "Honey", "Puff Pastry", "Love", "Wawa"],
"image" : "http://assets.simplyrecipes.com/wp-content/forum/uploads/2008/02/baklava-horiz-a-640.jpg"
},
{
"name" : "Chips N' Dip",
"ingredients": ["Chips", "Dip"],
"image" : "http://dinnerthendessert.com/wp-content/forum/uploads/2015/09/Chips-and-Guac-Small-680x453.jpg"
}
];
//This requires a recipe props of food, ingredietns, and an optional image, and prints specifically the recipe data
//The component deals with the drop down part of every recipe along with the buttons
class CollapseableRecipe extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
}
render() {
const title = (
<div>
<a className="panelHead"onClick={()=>this.setState({open: !this.state.open})}>{this.props.food}</a>
<ButtonGroup className="add-delete">
<Button bsStyle="success">Add to shopping list</Button>
<Button bsStyle="danger">Delete Recipe</Button>
</ButtonGroup>
</div>
);
let ingredients = this.props.ingredients.map((item) => {
return (<ListGroupItem key={item}>{item}</ListGroupItem>)
});
let style = {
"width": "100%",
"height": "100%",
"borderColor": "rgb(42, 42, 42)",
"borderWidth": "5px",
"borderRadius": "10px",
"marginBottom": "2%"
};
return (
<div>
<Panel collapsible expanded={this.state.open} header={title}>
<div>
<h1 className ="text-center">{this.props.food}</h1>
{this.props.image &&
<img src={this.props.image} style={style}></img>
}
<ListGroup>
{ingredients}
</ListGroup>
</div>
</Panel>
</div>
)
}
};
class AddToList extends React.Component {
constructor(props) {
super(props);
this.state=({
showModal: false
});
}
handleClick() {
this.setState({ showModal : true});
}
close() {
this.setState({ showModal : false});
}
updateRecipes() {
if ($('#title').val() && $('#ingredients').val()) {
let recipe = {
"name" : $('#title').val(),
"ingredients" : $('#ingredients').val()
};
if ($('#image').val()) {
recipe["image"] = $('#image').val();
}
this.props.update(recipe);
this.close();
}
alert("Hold up! You gotta fill in the necessary boxes!");
}
render() {
$('body').click(function (event) {
if(!$(event.target).closest('#openModal').length && !$(event.target).is('#openModal')) {
$(".modalDialog").hide();
}
});
const myModal = (
<Modal show={this.state.showModal} onHide={() => this.close()} bsSize="large" aria-labelledby="contained-modal-title-lg">
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-lg">Add a new recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<h3>Name of Dish</h3>
<input type="text" label="Recipe" placeholder="Recipe Name" id="title" />
<h3>Ingredients</h3>
<input type="textarea" label="Ingredients" placeholder="Enter Ingredients(commas to separate)" id="ingredients"/>
<h3>Image</h3>
<input type="textarea" label="Image" placeholder="Enter a URL to an image(optional)" id="image"/>
</form>
</Modal.Body>
<Modal.Footer>
<Button bsStyle="success" id="addRec" onClick={()=> this.updateRecipes()}>Add Recipe</Button>
</Modal.Footer>
</Modal>
);
return (
<div>
<button onClick={()=> this.handleClick()} className="addThings">+</button>
{myModal}
</div>
);
}
}
class FullBox extends React.Component {
constructor(props) {
super(props);
this.state = ({
recipes:[
{
"name" : "Baklava",
"ingredients": ["Flower", "Baking soda", "Pistachios", "Honey", "Puff Pastry", "Love", "Wawa"],
"image" : "http://assets.simplyrecipes.com/wp-content/forum/uploads/2008/02/baklava-horiz-a-640.jpg"
},
{
"name" : "Chips N' Dip",
"ingredients": ["Chips", "Dip"],
"image" : "http://dinnerthendessert.com/wp-content/forum/uploads/2015/09/Chips-and-Guac-Small-680x453.jpg"
}
]
});
this.updateStatefulRecipes = this.updateStatefulRecipes.bind(this);
}
updateStatefulRecipes(recipe) {
var newArr = this.state.recipes.concat(recipe);
this.setState({
recipes: newArr
});
}
render() {
let localRecipes = this.state.recipes.map((item) => {
return <CollapseableRecipe key={item["name"]} food={item["name"]} ingredients={item["ingredients"]} image={item["image"]} />
});
return (
<div>
{localRecipes}
<AddToList update={this.updateStatefulRecipes} recipes={this.state.recipes}/>
</div>
);
}
};
ReactDOM.render(<FullBox />, document.getElementById('render-target'));