首页 > 解决方案 > 用参数反应路由器 dom 链接并不总是有效

问题描述

我写了一个简单的搜索组件,在反应中带有自动建议,它调用 themoviedb。我正在使用 react-router-dom 并在 app.js 中定义了这样的路由参数:

<Route path="/:id" component={SomeComponent} />

搜索组件如下所示:

import React, { Component, Fragment } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import axios from "axios";

const SuggestionsResult = styled.ul`
  text-decoration: none;
  list-style: none;
  text-align: left;
  display: flex;
  flex-direction: column;
  width: 100%;
`;

const ResultItem = styled.li`
  border-bottom: 0.0625rem solid hsla(0, 0%, 100%, 0.12);
  padding: 10px 0 10px;
  padding-left: 2px;
  font-size: 1em;
  cursor: pointer;
  &:hover {
    background: hsla(0, 0%, 100%, 0.12);
  }
`;

export default class Search extends Component {
  state = {
    query: "",
    results: [],
    showSuggestions: false
  };

  handleInputChange = () => {
    this.setState(
      {
        query: this.search.value
      },
      () => {
        if (this.state.query && this.state.query.length > 1) {
          if (this.state.query.length % 2 === 0) {
            axios
              .get(
                `https://api.themoviedb.org/3/search/movie?api_key=${apiKey}&language=en-US&query=${
                  this.state.query
                }&page=1&include_adult=false`
              )
              .then(({ data }) => {
                this.setState({
                  results: data.results,
                  showSuggestions: !this.state.showSuggestions
                });
              });
          }
        } else if (!this.state.query) {
        }
      }
    );
  };



  handleSuggestionClick = e => {
    this.setState({ showSuggestions: false });
  };

  render() {
    return (
      <Fragment>
        <input
          placeholder="Search for a movie..."
          ref={input => (this.search = input)}
          onChange={this.handleInputChange}
        />
        {this.state.showSuggestions && (
          <Suggestions
            results={this.state.results}
            handleSuggestionClick={this.handleSuggestionClick}
          />
        )}
      </Fragment>
    );
  }
}

const Suggestions = ({ results, handleSuggestionClick }) => {
  const options = results.map(r => (
    <ResultItem key={r.id}>
      <Link onClick={handleSuggestionClick} to={`/${r.id}`}>
        {r.title}
      </Link>
    </ResultItem>
  ));
  return <SuggestionsResult>{options}</SuggestionsResult>;
};

我的问题是单击链接时它会更改 url 但它仍然在同一个站点上。如果我不使用 react-router-dom Link 组件而只使用一个元素,它可以正常工作,但一切都会重新渲染。

** 在 app.js 中更新我的 react-router 代码

<Router>
  <Switch>
        <Route exact path="/" component={MoviesList} />
        <Route path="/:id" component={MovieDetail} />
   </Switch>
</Router>

标签: reactjsreact-routerreact-router-v4react-router-dom

解决方案


Suggestions 组件没有接收到 Router 属性,因此会导致此问题。withRouter用HOC包装你的 Suggestions 组件。还要确保将 Search 组件呈现为子组件或Router组件

import React, { Component, Fragment } from "react";
import { Link, withRouter } from "react-router-dom";
import styled from "styled-components";
import axios from "axios";

const SuggestionsResult = styled.ul`
  text-decoration: none;
  list-style: none;
  text-align: left;
  display: flex;
  flex-direction: column;
  width: 100%;
`;

const ResultItem = styled.li`
  border-bottom: 0.0625rem solid hsla(0, 0%, 100%, 0.12);
  padding: 10px 0 10px;
  padding-left: 2px;
  font-size: 1em;
  cursor: pointer;
  &:hover {
    background: hsla(0, 0%, 100%, 0.12);
  }
`;

export default class Search extends Component {
  state = {
    query: "",
    results: [],
    showSuggestions: false
  };

  handleInputChange = () => {
    this.setState(
      {
        query: this.search.value
      },
      () => {
        if (this.state.query && this.state.query.length > 1) {
          if (this.state.query.length % 2 === 0) {
            axios
              .get(
                `https://api.themoviedb.org/3/search/movie?api_key=${apiKey}&language=en-US&query=${
                  this.state.query
                }&page=1&include_adult=false`
              )
              .then(({ data }) => {
                this.setState({
                  results: data.results,
                  showSuggestions: !this.state.showSuggestions
                });
              });
          }
        } else if (!this.state.query) {
        }
      }
    );
  };



  handleSuggestionClick = e => {
    this.setState({ showSuggestions: false });
  };

  render() {
    return (
      <Fragment>
        <input
          placeholder="Search for a movie..."
          ref={input => (this.search = input)}
          onChange={this.handleInputChange}
        />
        {this.state.showSuggestions && (
          <Suggestions
            results={this.state.results}
            handleSuggestionClick={this.handleSuggestionClick}
          />
        )}
      </Fragment>
    );
  }
}

const Suggestions = withRouter(({ results, handleSuggestionClick }) => {
  const options = results.map(r => (
    <ResultItem key={r.id}>
      <Link onClick={handleSuggestionClick} to={`/${r.id}`}>
        {r.title}
      </Link>
    </ResultItem>
  ));
  return <SuggestionsResult>{options}</SuggestionsResult>;
});

推荐阅读