简体   繁体   中英

React rendering both components on partial route match

I am currently getting started with react and have two routes defined as such:

<Route path='/articles' component={ArticlesIndex} />
<Route path='/articles/create' component={ArticlesCreate} />

When visiting /articles , only my ArticlesIndex component is rendered as I'd expect. However, when navigating to /articles/create , both my ArticlesIndex and ArticlesCreate components are both being rendered on the page despite my ArticlesCreate component having no reference to ArticlesIndex . It seems as though the react router is rendering the ArticlesIndex component due to the route being contained in articles/create .

How can I overcome this?

For completeness' sake, Here are my two components:

ArticlesIndex component:

import React, { Component } from 'react'

export class ArticlesIndex extends Component {
  displayName = ArticlesIndex.name

  constructor(props) {
    super(props)
    this.state = { articles: [], loading: true }

    fetch('https://localhost:44360/api/Articles/')
      .then(response => response.json())
      .then(data => {
        this.setState({ articles: data, loading: false })
      })
  }

  static renderArticlesTable(articles) {
    return (
      <table className="table">
        <thead>
          <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          {articles.map(article => (
            <tr key={article.id}>
              <td>{article.id}</td>
              <td>{article.title}</td>
              <td>{article.description}</td>
            </tr>
          ))}
        </tbody>
      </table>
    )
  }

  render() {
    let contents = this.state.loading ? (
      <p>
        <em>Loading...</em>
      </p>
    ) : (
      ArticlesIndex.renderArticlesTable(this.state.articles)
    )

    return (
      <div>
        <h1>Articles</h1>
        {contents}
      </div>
    )
  }
}

and ArticlesCreate component:

import React, { Component } from 'react'

export class ArticlesCreate extends Component {
  displayName = ArticlesCreate.name

  constructor(props) {
    super(props)
    this.state = {
      title: '',
      description: '',
    }

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

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <div className="form-group row">
          <label className=" control-label col-md-12" htmlFor="Title">
            Title
          </label>
          <div className="col-md-4">
            <input
              className="form-control"
              type="text"
              name="title"
              defaultValue={this.state.title}
              required
            />
          </div>
        </div>
        <div className="form-group row">
          <label className=" control-label col-md-12" htmlFor="Description">
            Description
          </label>
          <div className="col-md-4">
            <input
              className="form-control"
              type="text"
              name="description"
              defaultValue={this.state.description}
              required
            />
          </div>
        </div>
        <div className="form-group">
          <button type="submit" className="btn btn-default">
            Save
          </button>
        </div>
      </form>
    )
  }

  handleSubmit(event) {
    event.preventDefault()
    const data = new FormData(event.target)

    // POST request for Add employee.
    fetch('https://localhost:44360/api/Articles/', {
      method: 'POST',
      body: data,
    })
      .then(response => response.json())
      .then(responseJson => {
        this.props.history.push('/articles')
      })
  }
}

You forgot to add the exact props on your <Route /> and the url /articles/create is matching both routes.

When exact={true} or exact is passed into <Route/> props the Route will be rendering the component if the location.pathname match exactly you path .

<Route exact={true} path='/articles' component={ArticlesIndex} />
<Route path='/articles/create' component={ArticlesCreate} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM