在 componentDidMount - react-router-dom v6 中导航

navigate in componentDidMount - react-router-dom v6

我第一次使用react-router-dom v6,我熟悉v4。

我有一个电影列表,每部电影都有一个 ID,如果用户在 url 中输入了错误的电影 ID,我需要导航到未找到的页面。

我正在使用 class 组件的问题,所以我坚持使用 componentDidMount 导致以下错误

You should call navigate() in a React.useEffect(), not when your component is first rendered.

这是我的代码:

 componentDidMount() {
    let { id } = this.props.params;
    const genres = getGenres();
    this.setState({ genres });
    const movieId = id;
    if (movieId === 'new') return;
    const movie = getMovie(movieId);
    if (!movie) return this.props.navigate('/not-found', { replace: true });
    this.setState({ data: this.mapToViewModel(movie) });
  }

如前所述,我正在使用 class 组件,因此我将 class 作为函数导出,以使 Useparams() 与我一起工作

function WithNavigate(props) {
  let navigate = useNavigate();
  return <MovieForm {...props} params={useParams()} navigate={navigate} />;
}

export default WithNavigate;

我现在的问题是如何使导航在 componentDidMount 中工作!

提前致谢

嗯,实际的解决方案是如何使用 useNavigate,或者您可以制作 wrapperComponent 使其成为通用解决方案,您可以在代码库的任何地方使用它

import { useNavigate } from 'react-router-dom';

export const withNavigate = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();
    
    return (
      <Component
        navigate={navigate}
        {...props}
        />
    );
  };
  
  return Wrapper;
};

现在你只有一个包装函数,你所要做的就是将你的组件包装在你想使用的地方 useNavigate 并像这样使用它 this.props.navigate('/not-found')

import React from 'react';
import {withNavigate} from 'src/hooks/withNavigate';

class MovieForm extends React.Component{
  // .... rest of the code


 componentDidMount() {
    let { id } = this.props.params;
    const genres = getGenres();
    this.setState({ genres });
    const movieId = id;
    if (movieId === 'new') return;
    const movie = getMovie(movieId);
    if (!movie) return this.props.navigate('/not-found');
    this.setState({ data: this.mapToViewModel(movie) });
  }



  // .... rest of the code
}

export default withNavigate(MovieForm);

componentDidMountuseEffect()

之后渲染

对于简单的修复,您可以添加

let { navigate } = this.props;

像这样添加您的代码,setTimeOut

 componentDidMount() {
    let { id } = this.props.params;
    let { navigate } = this.props;

    const genres = getGenres();
    this.setState({ genres });
    const movieId = id;

    if (movieId === 'new') return;
    const movie = getMovie(movieId);
    if (!movie) {
           return setTimeOut(()=> this.props.navigate('/not-found', { replace: true }));
    }
    this.setState({ data: this.mapToViewModel(movie) });
  }

您 defining/using WithNavigate 作为 React 包装器组件而不是作为高阶组件,这改变了 useNavigate 挂钩的使用方式和传递给 class组件。

而不是

function WithNavigate(props) {
  let navigate = useNavigate();
  return <MovieForm {...props} params={useParams()} navigate={navigate} />;
}

转换为 HOC

function withNavigate = Component => props => {
  const navigate = useNavigate();
  const params = useParams();

  return <Component {...props} params={params} navigate={navigate} />;
}

export default withNavigate;

然后装饰MovieForm组件为默认导出

export default withNavigate(MovieForm);