Как передать данные из компонента, на который нажали, из одного маршрута в другой в React? - PullRequest
0 голосов
/ 10 ноября 2018

Я работаю над приложением для поиска видеоигр, которое получает данные из GiantBomb API с помощью React Router. Когда поиск выполняется в компоненте SearchGames, он возвращает список игр из API через компонент Game. Я застрял в том, чтобы выяснить, как передать данные о перечисленной игре, которую вы щелкаете, в компонент GamesDetail с помощью Router. Я не думаю, что смогу сделать это с помощью реквизита, поскольку отдельное представление со всеми деталями не является ни родительским, ни дочерним компонентом. Я надеюсь, что то, что я спрашиваю, имеет смысл.

class App extends Component {
  render() {
    return (
      <Router>
        <div className="App">
          <Nav />
          <div className="container">
            <Switch>
              <Route exact path="/" component={MainPage} />
              <Route exact path="/games" component={GameSearch} />
              <Route exact path="/about" component={About} />}
              <Route exact path="/details" component={GamesDetails} />}
            </Switch>
          </div>
        </div>
      </Router>
    );
  }
}

class Search extends Component {
      constructor(props) {
        super(props);
        this.state = {
          title: "",
          games: []
        }
      }

  updateInput = (event) => {
    this.setState({
      title: event.target.value
    });
  }

  handleGames = (search) => {
    const proxyUrl = "https://cors-anywhere.herokuapp.com/";
    const key = "8cd10a7136710c1003c8e216d85941ace5a1f00e";
    const endpoint = `https://www.giantbomb.com/api/search/?api_key=`;
    const url = proxyUrl + endpoint + key + `&format=json&resources=game&query=${search}&limit=30`;

    fetch(url)
      .then(res => res.json())
      .then(data => {
        const response = data.results;
        console.log(response);
        response.forEach(game => {
          this.setState(prevState => ({
            games: prevState.games.concat(game)
          }))
        });
      });

    this.setState({
      games: []
    })

  }

  handleSubmit = (e) => {
    const { title } = this.state;

    e.preventDefault();

    if (!title) {
      return;
    } else {
      this.handleGames(title);
    }

  }

  render() {
    const { games } = this.state;
    return (

      <div className="App">
        <div className="search-bar">
          <form>
            <input
              className="input-field"
              type="text"
              placeholder="Search Game"
              onChange={this.updateInput}
            />
            <button
              className="search-button"
              onClick={this.handleSubmit}
            >Search</button>
          </form>
        </div>
        <div className="container">
          {games.length > 0 ? (
            games.map(game => {
              return <Game
                key={game.id}
                icon={game.image.icon_url}
                gameTitle={game.name}
              />
            })
          ) : (
              console.log(this.state.title)
            )
          }


        </div>
      </div>

    );
  }
}

const Game = (props) => {
  const { icon, gameTitle } = props;
  return (
    <div className="games-container">
      <div className="game-box">
        <img src={icon} alt="icon" />
        <Link to="/details">
          <p><strong>{gameTitle}</strong></p>
        </Link>
      </div>
    </div>
  );
}

const GameDetails = (props) => {
  const { icon, release, genres, summary} = props;
  return (
    <div className="details-content">
      <div className="box-art">
        <img src={icon} alt="box art" />
      </div>
      <div className="game-info">
        <h1>Game Details</h1>
        <div className="release-date">
          <h3>Release Data</h3>
          <p>{release}</p>
        </div>
        <div className="genres">
          <h3>Genres</h3>
          <p>{.genres}</p>
        </div>
        <div className="summary">
          <h3>Summary</h3>
          <p>{summary}</p>
        </div>
      </div>
    </div>
  );
}

1 Ответ

0 голосов
/ 10 ноября 2018

Этого можно достичь, используя Link с to в качестве объекта , который выставляет state, который может быть передан полученному Route:

// ...
// pass game object to Game component
// if you are passing game, you probably don't need other props explicitly passed
{games.length > 0 ? (
  games.map(game => {
    return <Game
      key={game.id}
      game={game}
      icon={game.image.icon_url}
      gameTitle={game.name}
    />
  })
 ) : (
   console.log(this.state.title)
 )
}

// ...

const Game = (props) => {
  const { icon, gameTitle, game } = props;

  return (
    <div className="games-container">
      <div className="game-box">
        <img src={icon} alt="icon" />
        <Link to={{ pathname: "/details", state: { game } }}>
          <p><strong>{gameTitle}</strong></p>
        </Link>
      </div>
    </div>
  );
}

Затем вы можете получить доступ к этому state из реквизита местоположения , которое react-router-dom вводит в props:

const GamesDetails = (props) => {
  const { image: { icon_url: icon }, release, genres, summary } = props.location.state.game;

  return (
    <div className="details-content">
      <div className="game-info">
        <h1>Game Details</h1>
        <div className="box-art">
          <img src={icon} alt="box art" />
        </div>
        <div className="release-date">
          <h3>Release Data</h3>
          <p>{release}</p>
        </div>
        <div className="genres">
          <h3>Genres</h3>
          <p>{genres}</p>
        </div>
        <div className="summary">
          <h3>Summary</h3>
          <p>{summary}</p>
        </div>
      </div>
    </div>
  );
}

Вот пример в действии.

Надеюсь, это поможет!

...