Итак, у меня есть роутер и компонент. Когда я вызываю history.push из одного компонента в тот же компонент, но с разными параметрами URL, componentDidMount не срабатывает.

App.JS

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


import Footer from './components/Footer'
import history from './History'

import './App.css';
import 'semantic-ui-css/semantic.min.css'
import ScrollToTop from "./components/ScrollToTop";

const Home = lazy(() => import('./pages/Home'));
const Terms = lazy(() => import('./pages/TermsOfService'));
const Search = lazy(() => import('./pages/Search'));
const JobDetail = lazy(() => import('./pages/Detail'));
const PostJob = lazy(() => import('./pages/PostAJob'));
const Category = lazy(() => import('./pages/Category'));
const New = lazy(() => import('./pages/New'));
const Blog = lazy(() => import('./pages/Blog'))
const BlogDetail = lazy(() => import('./pages/BlogDetail'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Router history={history}>
          <ScrollToTop />
          <Switch>
            <Route strict exact path="/" component={Home} />
            <Route strict exact path="/search/:query" component={Search} />
            <Route strict exact path="/new" component={New} />
            <Route strict exact path="/terms-of-service" component={Terms} />
            <Route strict exact path="/post-a-job" component={PostJob} />
            <Route strict exact path="/category/:cat" component={Category} />
            <Route strict exact path="/category/:cat/:page?" component={Category} />
            <Route strict exact path="/privacy-policy" />
            <Route strict exact path="/blog" component={Blog}/>
            <Route strict exact path="/blog/page/:page" component={Blog}/>
            <Route strict exact path="/blog/:slug" component={BlogDetail} />
            <Route strict exact path='/:slug' component={JobDetail} />
            <Route path="*" />
          </Switch>
        <Footer />
      </Router>
    </Suspense>
  );
}

export default App;

Составная часть

import React from 'react';
import axios from 'axios';
import { Container, Grid, Rail, Pagination } from 'semantic-ui-react';
import {categoryCopy} from '../utilities/index'
import JobCard from '../components/JobCard';
import slugify from 'slugify'
import Nav from '../components/Navbar';
import '../scss/category.scoped.scss';

class Category extends React.PureComponent {
  constructor() {
    super()

    this.state = {
      jobs: null,
      loading: false,
      total_pages: 0,
      active_page: 0,
    }

    this.onPageChange = this.onPageChange.bind(this)
  }

  async componentDidMount() {
    const {props: {match: {params: {page}}}} = this
    const realPage = page || 1
    console.log(realPage, 'REAL')

    try {
      const results = await axios.get(`https://api.theremotejob.io/jobs/category/${this.parseCategory(this.props.match.params.cat)}?page=${realPage}`)
      const body = results?.data?.data
      this.setState({loading: false, jobs: body ? body : null, total_pages: results?.data?.total_pages, active_page: parseInt(results?.data?.current_page, 10)})
    } catch (e) {
      this.setState({loading: false, results: []})
      console.error(e)
    }
  }

  parseCategory(cat) {
    cat = cat.toLowerCase()
    cat = cat.replace(/(, | and )/g, '_')
    cat = cat.replace(/ /g, '+')
    return cat
  }

  findText() {
    const cat = this.props.match.params.cat;
    // eslint-disable-next-line
    for (const c of categoryCopy) {
      const key = slugify(c.key, {lower: true});
      if(key === cat) {
        return c.copy;
      }
    }
  }

  parseHeader() {
    const cat = this.props.match.params.cat;
    return cat.replace(/-/g, ' ').split(" ").map((word) => {
      if(word !== 'and') {
        return word[0].toUpperCase() + word.substring(1);
      } else {
        return word
      }
    }).join(" ");
  }

  onPageChange(_, data) {
    window.location.href =`/category/${this.props.match.params.cat}/${data.activePage}`
  }

  render() {
    const {state: {jobs, total_pages, active_page}} = this
    return (
      <>
      <Nav hideNav={false} history={this.props.history} />
      <Container className="category">
        <Grid centered>
          <Grid.Column width={10}>
            <h1>{this.parseHeader()}</h1>
            <p>{this.findText()}</p>
            <ul>
              {jobs && jobs.map((el, id) => {
                return (
                  <JobCard data={el} key={id}/>
                )
              })}
              </ul>
              <Rail dividing position='left'>

              </Rail>

              <Rail dividing position='right'>

              </Rail>
              <div className="pagination-container">
                <Pagination
                  defaultActivePage={active_page}
                  totalPages={total_pages}
                  onPageChange={(e, data) => this.onPageChange(e, data)}/>
              </div>
            </Grid.Column>
          </Grid>
        </Container>
      </>
    );
  }
}
export default Category;

Как я могу это исправить? Похоже на странное поведение.

0
Quesofat 22 Фев 2021 в 00:39

1 ответ

Лучший ответ

Это ожидается как стратегия оптимизации. Давайте посмотрим на документацию по реактивному маршрутизатору:

https://reactrouter.com/web/api/Route

Если один и тот же компонент используется как дочерний для нескольких s в одной и той же точке в дереве компонентов, React увидит это как один и тот же экземпляр компонента, и состояние компонента будет сохраняться между изменениями маршрута. Если это нежелательно, уникальное ключевое свойство, добавленное к каждому компоненту маршрута, заставит React воссоздать экземпляр компонента при изменении маршрута.

https://codesandbox.io/s/exciting-pike-bv1ij?file=/src/App.js

Если вы хотите снова запустить componentDidMount, просто используйте опору key. Он будет отключен, а затем смонтировать ваши компоненты по мере изменения вашего маршрута.

<Route exact path="/category/:cat" key="default" component={Category} />
<Route exact path="/category/:cat/:page?" key="first-page" component={Category}
0
richardaum 21 Фев 2021 в 22:11