首页 > 解决方案 > react router 改变了url,但是组件没有渲染

问题描述

我有一个使用 API 并呈现列表的组件。每个列表项都有一个自定义链接来重定向到它的页面。

我试图让这条路线获取 URL 参数,以显示其他组件。

但是,尽管 URL 发生了变化,但当我单击列表项时,其他组件永远不会呈现。但有趣的是,如果我手动输入 URL,它就会呈现。

这是我的代码:

应用程序.js

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

// import Routes from "./routes";
import Navbar from "./components/Navbar";
import GlobalStyle from "./styles/global";

import Main from "./pages/Main";
import Hero from "./pages/Hero";
import Favorites from "./pages/Favorites";

const App = () => (
  <Router>
    <GlobalStyle />
    <Navbar />
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/favorites">Favoritos</Link>
      </li>
    </ul>
    <Switch>
      {/* <Main path="/hero/:heroId" component={Hero} /> */}
      <Route path="/hero" component={Hero} />
      <Route path="/favorites" component={Favorites} />
      <Route path="/" exact component={Main} />

      {/* <Route path="/hero" render={props => <Hero {...props} />} /> */}
    </Switch>
  </Router>
);
export default App;

主.js

import React, { Component } from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
import api from "../../services/api";
import md5 from "js-md5";

import { SearchBar, SearchInput, SearchButton, Wrapper } from "./styles";

import Card from "../../components/Card";

export default class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      heroes: [],
      search: ""
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  componentDidMount() {
    this.loadHeroes();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.searc !== this.state.search) {
      this.loadHeroes();
    }
  }

  loadHeroes = async () => {
    const PUBLIC_KEY = process.env.REACT_APP_PUBLIC;
    const PRIVATE_KEY = process.env.REACT_APP_PRIVATE;
    const timestamp = Number(new Date());
    const hash = md5.create();
    hash.update(timestamp + PRIVATE_KEY + PUBLIC_KEY);

    if (this.state.search === "") {
      await api
        .get(`/characters?ts=${timestamp}&apikey=${PUBLIC_KEY}&hash=${hash}`)
        .then(response =>
          this.setState({ heroes: response.data.data.results })
        );
    } else {
      await api
        .get(
          `/characters?nameStartsWith=${this.state.search}&ts=${timestamp}&apikey=${PUBLIC_KEY}&hash=${hash}`
        )
        .then(response =>
          this.setState({ heroes: response.data.data.results })
        );
    }
  };

  handleChange(event) {
    this.setState({ search: event.target.value });
  }

  handleSubmit(event) {
    console.log("State do search: ", this.state.search);
    event.preventDefault();
  }

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

    let filteredHeroes = heroes.filter(
      hero => hero.name.toLowerCase().indexOf(this.state.search) !== -1
    );

    return (
      <div>
        <SearchBar onSubmit={this.handleSubmit}>
          <label>
            Buscar
            <SearchInput
              onChange={this.handleChange}
              type="search"
              value={this.state.search}
            />
          </label>
          <SearchButton type="submit" value="Enviar" />
        </SearchBar>

        <Router>
          <Wrapper>
            {filteredHeroes.map(hero => {
              return (
                <Link
                  to={`hero?q=${hero.id}`}
                  style={{ textDecoration: "none" }}
                  key={hero.id}
                >
                  <Card name={hero.name} thumbnail={hero.thumbnail} />
                </Link>
              );
            })}
          </Wrapper>
        </Router>
      </div>
    );
  }
}

Hero.js

import React from "react";

const Hero = props => {
  return (
    <div>
      <h1>{props.name}</h1>

      <article>
        <p>
          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima
          accusamus ducimus qui amet quis? Non rerum consequuntur soluta,
          voluptatum blanditiis explicabo, laudantium architecto distinctio enim
          aliquid placeat, quaerat voluptas totam!
        </p>
      </article>
    </div>
  );
};

export default Hero;

标签: reactjsreact-router

解决方案


在您的代码中进行以下更改!

应用程序.js

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

// import Routes from "./routes";
import Navbar from "./components/Navbar";
import GlobalStyle from "./styles/global";

import Main from "./pages/Main";
import Hero from "./pages/Hero";
import Favorites from "./pages/Favorites";

const App = () => (
  <Router>
    <GlobalStyle />
    <Navbar />
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/favorites">Favoritos</Link>
      </li>
    </ul>
    <Switch>
      <Route path="/" exact component={Main} />
      <Route path="/hero" exact component={Hero} />
      <Route path="/favorites" exact component={Favorites} />
    </Switch>
  </Router>
);
export default App;

主.js

import React, { Component } from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
import api from "../../services/api";
import md5 from "js-md5";

import { SearchBar, SearchInput, SearchButton, Wrapper } from "./styles";

import Card from "../../components/Card";

export default class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      heroes: [],
      search: ""
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  componentDidMount() {
    this.loadHeroes();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.searc !== this.state.search) {
      this.loadHeroes();
    }
  }

  loadHeroes = async () => {
    const PUBLIC_KEY = process.env.REACT_APP_PUBLIC;
    const PRIVATE_KEY = process.env.REACT_APP_PRIVATE;
    const timestamp = Number(new Date());
    const hash = md5.create();
    hash.update(timestamp + PRIVATE_KEY + PUBLIC_KEY);

    if (this.state.search === "") {
      await api
        .get(`/characters?ts=${timestamp}&apikey=${PUBLIC_KEY}&hash=${hash}`)
        .then(response =>
          this.setState({ heroes: response.data.data.results })
        );
    } else {
      await api
        .get(
          `/characters?nameStartsWith=${this.state.search}&ts=${timestamp}&apikey=${PUBLIC_KEY}&hash=${hash}`
        )
        .then(response =>
          this.setState({ heroes: response.data.data.results })
        );
    }
  };

  handleChange(event) {
    this.setState({ search: event.target.value });
  }

  handleSubmit(event) {
    console.log("State do search: ", this.state.search);
    event.preventDefault();
  }

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

    let filteredHeroes = heroes.filter(
      hero => hero.name.toLowerCase().indexOf(this.state.search) !== -1
    );

    return (
      <div>
        <SearchBar onSubmit={this.handleSubmit}>
          <label>
            Buscar
            <SearchInput
              onChange={this.handleChange}
              type="search"
              value={this.state.search}
            />
          </label>
          <SearchButton type="submit" value="Enviar" />
        </SearchBar>
          <Wrapper>
            {filteredHeroes.map(hero => {
              return (
                <Link
                  to={`/hero?q=${hero.id}`}
                  style={{ textDecoration: "none" }}
                  key={hero.id}
                >
                  <Card name={hero.name} thumbnail={hero.thumbnail} />
                </Link>
              );
            })}
          </Wrapper>
      </div>
    );
  }
}

并且无需更改 Herocomponent。


推荐阅读