如何在React中将数据从单击的组件从一条路径传递到另一条路径?

时间:2018-11-10 02:03:54

标签: javascript reactjs router

我正在开发一个视频游戏搜索应用程序,该应用程序使用React Router从GiantBomb API中获取数据。在SearchGames组件上完成搜索后,它会通过Game组件从API返回游戏列表。我坚持要弄清楚如何使用路由器将单击的列出游戏的数据详细信息传递给GamesDetail组件。我认为我无法使用props来完成此操作,因为具有所有详细信息的单独视图既不是父组件也不是子组件。我希望我的要求是有道理的。

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 :(得分:1)

您应该能够使用Linkto作为object来实现此目的,它公开了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的道具location中访问此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>
  );
}

这里是example的动作。

希望有帮助!