data.map不是函数反应

时间:2020-02-28 14:10:52

标签: javascript reactjs

经过数小时的尝试纠正代码后,我来这里寻求帮助。 这个想法是寻找一个角色,并显示一些我选择的细节,现在 我根本无法解决这个问题,因为我尝试对死亡数组进行迭代并从那里收集一些信息:

我正在使用以下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。

任何帮助将不胜感激!

2 个答案:

答案 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'));