Невозможно получить доступ к подробной информации из Api с помощью React Router, который не отображается на странице - PullRequest
0 голосов
/ 15 апреля 2020

Я создаю небольшое приложение React Routing, чтобы лучше понять, как оно работает. Мое приложение. js выглядит следующим образом с базовой c маршрутизацией:

import React from 'react';
import './App.css';
import Nav from './Nav';
import About from './About';
import Shop from './Shop';
import CountryDetail from './CountryDetail'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

function App() {
  return (
    <Router>
      <div className="App">
        <Nav />
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/about" component={About} />
          <Route path="/shop" exact component={Shop} />
          <Route path="/shop/:name" component={CountryDetail} />
        </Switch>
      </div>
    </Router>
  );
}

const Home = () => (
  <div>
    <h1>Home Page</h1>
  </div>
);

Теперь компонент "Магазин" представляет список стран из API, который находится в коде ниже:

import React from 'react';
import './App.css';
import { useEffect } from 'react';
import { useState } from 'react';
import {Link} from 'react-router-dom';

function Shop() {

  useEffect(() => {
    fetchItems();
  },[])

  const [countries, setCountries] = useState([])

  const fetchItems = async () => {
    const data = await fetch('https://restcountries.eu/rest/v2/all');
    const countries = await data.json();
    console.log(countries);
    setCountries(countries);
  }

  return (
    <div>
      {countries.map(country => (
        <div>
          <Link to={`shop/${country.name}`}>
            <h1 key={country.alpha2Code}>
              {country.name}
            </h1>
          </Link>
          <p>Popluation {country.population}</p>
          <p> Region {country.region}</p>
          <p>Capital {country.capital}</p>
        </div>
        )
      )}
    </div>
  );
}

export default Shop;

Теперь я хочу показать больше информации о стране, когда я нажму на нее. Поэтому я создал еще один компонент с именем CountryDetail:

import React from 'react';
import './App.css';
import { useEffect } from 'react';
import { useState } from 'react';


function CountryDetail( { match } ) {

  useEffect(() => {
    fetchItem();
    console.log(match)
  },[])

  const [country, setCountry] = useState([])

  const fetchItem = async ()=> {
    const fetchCountry = await fetch(`https://restcountries.eu/rest/v2/name/${match.params.name}`);
    const country = await fetchCountry.json();
    setCountry(country);
    console.log(country);
  }

  return (
    <div>
      <h1>Name {country.name}</h1>
      <p>Native Name{country.nativeName}</p>
      <p>Region {country.region}</p>
      <p>Languages {country.languages}</p>
      <h1>This Country</h1>
    </div>
  );
}

export default CountryDetail;

Проблема, с которой я столкнулся, заключается в том, что он ничего не отображает на странице CountryDetail. Я уверен, что я ударил API правильно, но не уверен, что я получаю данные правильно. Любая помощь будет оценена.

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Проблема: Возвращенный JSON является массивом, но ваш JSX предполагает, что это объект.

Решение: Вы должны извлечь 0-й элемент из JSON массив. Окружить в try / catch в случае ошибки и правильно отобразить ответ.

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

function CountryDetail({ match }) {
  useEffect(() => {
    fetchItem();
    console.log(match);
  }, []);

  const [country, setCountry] = useState(null);

  const fetchItem = async () => {
    try {
      const fetchCountry = await fetch(
        `https://restcountries.eu/rest/v2/name/${match.params.name}`
      );
      const country = await fetchCountry.json();
      setCountry(country[0]);
      console.log(country[0]);
    } catch {
      // leave state alone or set some error state, etc...
    }
  };

  return (
    country && (
      <div>
        <h1>Name {country.name}</h1>
        <p>Native Name{country.nativeName}</p>
        <p>Region {country.region}</p>
        <p>Languages {country.languages.map(({ name }) => name).join(", ")}</p>
        <h1>This Country</h1>
      </div>
    )
  );
}

Edit affectionate-merkle-74weu

0 голосов
/ 15 апреля 2020

Как вы сказали сами, ответ - это массив (с одним объектом страны), но вы используете его, как если бы это был объект.

Итак, вместо:

const country = await fetchCountry.json();
setCountry(country);

Должно быть:

const countries = await fetchCountry.json();
setCountry(countries[0]);
...