Как отобразить только один результат в отдельном компоненте, используя axios в React? - PullRequest
0 голосов
/ 07 июня 2019

Редактировать //

Полагаю, мой вопрос не так ясен. Я пытаюсь вернуть один парк, когда мой URL-адрес указывает на http://localhost:1233/details/‘${parkcode}’. Я определил параметр для URL-адреса в моем файле results.js. Но у меня возникают проблемы с определением this.setState в файле details.js для отображения только одного результата парка на основе идентификатора, который также является кодом парка.

Я новичок в React (и, возможно, в JavaScript, я больше не знаю). Я следую учебному пособию - вместо использования пакета npm для API я решил разветвиться и использовать axios.get () для получения данных из API. Я могу отобразить результаты из компонента в браузер, однако после добавления на досягаемости маршрутизатора (я предполагаю, что он похож на React Router), у меня возникают проблемы при отображении только одного результата моего вызова API в качестве страницы, которую я пытаюсь выполнить. сборка должна показывать только ОДИН результат на основе идентификатора, который я определил.

В моем главном файле, который здесь представляет собой Results.js, я могу без проблем получить данные и включить их в свой файл с помощью JSX и отобразить их. Я пытаюсь использовать ту же логику, что и на этой странице на моей странице Details.js (на этой странице должен отображаться только один результат с идентификатором в маршруте).

Как я использую axios в Results.js

componentDidMount() {
    axios
      .get(
        "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +
          `${nps}`
      )

      // https://css-tricks.com/using-data-in-react-with-the-fetch-api-and-axios/
      .then(res =>
        res.data.data.map(park => ({
          description: `${park.description}`,
          fullname: `${park.fullName}`,
          states: `${park.states}`,
          parkcode: `${park.parkCode}`,
          image: `${park.images[0] ? park.images[0].url : "No Image"}`,
          designation: `${park.designation}`
        }))
      )
      .then(parks => {
        this.setState({
          parks
        });
        console.log(parks);
      });
  }

Как я пытаюсь использовать ту же логику в Details.js

Он не распознает park.name, хотя я сделал вызов API. Однако, если я жестко запрограммировал паркинг [0] .name, он работает. Я понятия не имею, что я делаю здесь не так. Это может быть очевидной проблемой, но помогите мне.

class Details extends React.Component {
  constructor (props) {
    super(props);

    this.state = {
      loading: true,
    }
  }

  componentDidMount() {
    axios
      .get(
        "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +
          `${nps}`, 
          { id: this.props.id }

      ).then(res => {
        const park = res.data.data.map(park => ({
          description: `${park.description}`,
          fullname: `${park.fullName}`,
          states: `${park.states}`,
          parkcode: `${park.parkCode}`,
          image: `${park.images[0] ? park.images[0].url : "No Image"}`,
          designation: `${park.designation}`
        }))

        console.log(park.name);

        this.setState({
          name: park.name;
          loading: false
        })
      }).catch(err => {
        this.setState({error: err});
      })
  }

Я ожидаю, что страница распознает идентификатор, как определено в GET-запросе, вместе с аксио, и отобразит детали парка относительно идентификатора. Но сейчас он ничего не делает, и я застрял на этом навсегда: (

Ответы [ 4 ]

0 голосов
/ 07 июня 2019

В вашем коде есть несколько ненужных частей. Вам не нужно создавать свои данные так, как вы это делаете в своей части setState. Вы получаете список парков, и это уже структурированные данные. Итак, просто установите свое состояние с данными, которые вы получите обратно.

После этого вы можете отобразить эти данные и отобразить парки со ссылками на React Router. Вы можете использовать parkCode в качестве параметра URL для Link. В компоненте Details вы можете извлечь этот parkCode и сделать новый запрос на информацию о парке, а затем установить его в своем штате.

Я привожу пример.

index.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Results from "./Results";
import Details from "./Details";

const Routes = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Results} />
      <Route path="/details/:parkCode" component={Details} />
    </Switch>
  </Router>
);

ReactDOM.render(<Routes />, document.getElementById("root"));

Результаты

import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";

class Results extends React.Component {
  state = {
    parks: [],
    loading: true,
  };

  componentDidMount() {
    axios(
      "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=LbqZVj21QMimfJyAHbPAWabFaBmfaTZtseq5Yc6t"
    ).then(res => this.setState({ parks: res.data.data, loading: false }));
  }

  renderParks = () =>
    this.state.parks.map(park => (
      <Link to={`/details/${park.parkCode}`} key={park.parkCode}>
        <div>{park.fullName}</div>
      </Link>
    ));

  render() {
    return (
      <div>{this.state.loading ? <p>Loading...</p> : this.renderParks()}</div>
    );
  }
}

export default Results;

подробности

import React from "react";
import axios from "axios";

class Details extends React.Component {
  state = { park: "", loading: true };

  componentDidMount() {
    const { match } = this.props;
    axios(
      `https://developer.nps.gov/api/v1/parks?parkCode=${match.params.parkCode}&api_key=${nps}`
    ).then(res => this.setState({ park: res.data.data[0], loading: false }));
  }

  render() {
    return (
      <div>
        {this.state.loading ? <p>Loading...</p> : this.state.park.description}
      </div>
    );
  }
}

export default Details;
0 голосов
/ 07 июня 2019

Вы можете попробовать это в .then()

let park = res.data.data.map(park => ({
    description: `${park.description}`,
    fullname:    `${park.fullName}`,
    states:      `${park.states}`,
    parkcode:    `${park.parkCode}`,
    image:       `${park.images[0] ? park.images[0].url : "No Image"}`,
    designation: `${park.designation}`
}))
park = park[0]; // convert arrays of parks to single park
console.log(park.fullname); // now you can use `park.fullname`

или это

const park = {
    description: `${res.data.data[0].description}`,
    fullname:    `${res.data.data[0].fullName}`,
    states:      `${res.data.data[0].states}`,
    parkcode:    `${res.data.data[0].parkCode}`,
    image:       `${res.data.data[0].images[0] ? park.images[0].url : "No Image"}`,
    designation: `${res.data.data[0].designation}`
}
console.log(park.fullname); // now you can use `park.fullname`

в противном случае сделайте это в API

0 голосов
/ 07 июня 2019

Я думаю, что вы можете сначала установить состояние для ваших ответов, а затем попытаться показать их

то же самое:

state = {
  result: []
}

componentDidMount() {
  axios
    .get("https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +`${nps}`).then((res) => {
      this.setState({result: res.data.data})
  })
}

render(){
  const result = this.state.result.map((el, index) => {
    return(
      //data
    )
  })
  return(
     <div>
       {result}
     </div>
  )
}
0 голосов
/ 07 июня 2019

Я считаю, что это та часть, в которой вы ошибаетесь

const parks = res.data.data.map(park => ({
  description: `${park.description}`,
  fullname: `${park.fullName}`,
  states: `${park.states}`,
  parkcode: `${park.parkCode}`,
  image: `${park.images[0] ? park.images[0].url : "No Image"}`,
  designation: `${park.designation}`
}))

console.log(parks) // this should display your array of all parks

this.setState({
  parks,
  loading: false
})

displayParks(parks) {
 const allParks = parks.map((park, index) => {
   return <div key={park.parkCode}>{park.fullname}<div>
 })
}


render() {
const { parks } = this.state;

const displayParks = parks && parks.length > 0 ? this.displayParks(parks) : <div>Loading parks</div>
  return (
      <div>{ displayParks }</div>
    );
  }

Когда вы создаете .map для массива, вы в основном создаете другой массив, и это то, что возвращается в вашу переменную park.

Таким образом, в вашем методе рендеринга вы можете зацикливаться на каждом элементе в parks

...