尝试导入错误:'useHistory'未从'react-router-dom'导出

337

useHistory 出现错误:

编译失败 ./src/pages/UserForm/_UserForm.js 尝试导入错误: 'useHistory' 未从 'react-router-dom' 导出。此错误发生在构建时,无法忽略。

react-router-dom 版本:

4.3.1

代码:

import React, { useState, Fragment } from 'react';
import FormUserDetails from './FormUserDetails';
import FormPersonalDetails from './FormPersonalDetails';
import Confirm from './Confirm';
import Success from './Success';
import Button from '@material-ui/core/Button';
import { Grid, makeStyles } from '@material-ui/core';
import { useHistory } from 'react-router-dom';


function UserForm() {
    const [step, setStep] = useState(1);
    const history = useHistory();


    const StepButtons = (props) => (
        <React.Fragment>
            <Grid item xs={4}>
                {props.value !== 'initial' ?
                    <Button variant="outlined" className={classes.button} onClick={(e) => previousStep(e)}>Back</Button> :
                    <Button variant="outlined" className={classes.button} onClick={(e) => reGenerate(e)}>Re-generate</Button>
                }
            </Grid>
            <Grid item xs={4} />
            <Grid item xs={4}>
                {
                    props.value === 'confirm' ?
                        <Button variant="outlined" className={classes.button} style={{ float: "right" }} onClick={(e) => confirm(e)}>Confirm</Button> :
                        props.value !== 'final' ?
                            <Button variant="outlined" className={classes.button} style={{ float: "right" }} onClick={(e) => nextStep(e)}>Continue</Button> :
                            null
                }
            </Grid>
        </React.Fragment>

    );
    const nextStep = (e) => {
        e.preventDefault();
        setStep(prevState => prevState + 1)
    }
    const previousStep = (e) => {
        e.preventDefault();
        setStep(prevState => prevState - 1)
    }
    const reGenerate = (e) => {
        e.preventDefault();
    }
    const confirm = (e) => {
        history.push('/')
    }
    return (
         <div>
            <h1>Hello</h1>
         </div>
    )
}
export default UserForm

React 版本如何?请注意:您需要使用 React >= 16.8 才能使用 useHistory 钩子! - norbitrial
2
React 版本已经是 16.8.4 了。感谢你指出 'react-router-dom' 的版本问题。@norbitrial - Nafeo Alam
13个回答

724
react-router-dom v6 中,useHistory()useNavigate() 替换了。
你可以使用:
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/home');

3
您在此处将页面硬编码以打开。如何在此处获取历史记录,以便我可以将用户导航到先前的页面?(原文已翻译) - ShashankAC
3
我花了足够的时间在react-router的Github资料上搜索,但没有找到任何关于'replaceHistory'替换的说明...也许它确实存在,但并不明显。感谢您让这一点变得明显! - SammyPayne
1
@ShashankAC 同意,这并不那么明显。请看我下面的答案:https://dev59.com/ZVIG5IYBdhLWcg3wzEzT#71394655 - lee_mcmullen
@SammyPayne 同意,这并不是那么明显。请看下面的答案:https://dev59.com/ZVIG5IYBdhLWcg3wzEzT#71394655 - lee_mcmullen
3
他们绝对不需要改变那个。现在我的雇主必须支付我时间来追赶react-router团队,就好像他们是我的竞争对手一样。组件维护者不应该让使用他们组件的人生活更加困难。这是标准的工程礼仪。 - Victor Pudeyev
1
navigate函数有两个签名:要么传递一个To值(与<Link to>相同的类型),带有可选的第二个{replace,state}参数;或者 传递您想要在历史堆栈中前进的增量。例如,navigate(-1)等同于点击后退按钮。 - Louis Huang

122

使用useNavigate替换useHistory,然后

const navigate = useNavigate();

然后将history.push('/path')替换为navigate('/path')

history.replace('/path')更改为navigate('/path', { replace: true })

如果想在push/navigate中使用state,请使用navigate('/path', { state: { name:'Xyz' }})


2
你是不是想使用 useNavigate(),因为 useNavigation() 会报错,提示没有导出成员。 - Thuy

43

没有一个答案实际上提到如何复制从v5 useHistory钩子中曾经可用但在v6中不再可用的方法,例如goBackgoForwardgo。 下面的示例摘自迁移指南

React Router v5应用程序使用来自useHistory钩子的方法:

// This is a React Router v5 app
import { useHistory } from "react-router-dom";

function App() {
  const { go, goBack, goForward } = useHistory();

  return (
    <>
      <button onClick={() => go(-2)}>
        Go 2 pages back
      </button>
      <button onClick={goBack}>Go back</button>
      <button onClick={goForward}>Go forward</button>
      <button onClick={() => go(2)}>
        Go 2 pages forward
      </button>
    </>
  );
}

这是使用 useNavigate 钩子的 navigate 方法实现 v6 等效应用的代码:

// This is a React Router v6 app
import { useNavigate } from "react-router-dom";

function App() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-2)}>
        Go 2 pages back
      </button>
      <button onClick={() => navigate(-1)}>Go back</button>
      <button onClick={() => navigate(1)}>
        Go forward
      </button>
      <button onClick={() => navigate(2)}>
        Go 2 pages forward
      </button>
    </>
  );
}

尝试导入错误:'useHistory'未从'react-router-dom'导出。 useHistory不再是一个导出成员,V6使用useNavigate() - M.Abdullah Iqbal
1
@M.AbdullahIqbal 感谢您的留言,是的,我的回答已经说了在v6中使用useNavigate() - lee_mcmullen

32

useHistory 在 v6 版本已被 useNavigate 取代。

只需将 useHistory 名称替换为 useNavigate,或按照以下三个简单步骤操作:

  1. 在文件开头添加import { useNavigate } from 'react-router-dom' ;

  2. 在函数中定义const navigate = useNavigate();

  3. navigate("/path_name"); 重定向到您的路径。


16

我已经将react-router-dom的版本升级到

5.2.0

现在它可以正常工作了。


没错,useHistory 是在 5.2.0 版本中推出的。 - Hidayt Rahman

9

V6 取消了 useHistory 钩子,现在使用 useNavigate 钩子。
用法

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

假设你有一个名为sendData的函数。

function sendData(){
    let data = {name,email,password}
    let results = await fetch('http://localhost:8000/api/register',{
        method:'POST',
        headers:{
            'Content-Type': 'application/json',
            'Accept':'application/json'
        },
        body:JSON.stringify(data)
    });
    results = await results.json();
    console.warn("results",results);
    localStorage.setItem('user',JSON.stringify(results))
    navigate('../add',{replace:true})
}

返回上一页:使用navigate('../add',{replace:true})

前往下一页:使用navigate('/add')


9
只需这样用 useNavigate 替换 useHistory:
import { useNavigate } from "react-router-dom";

那么

const navigate = useNavigate();

最后,
navigate("/home");

7

基于以上答案,如果问题存在于 v5,我添加了一个额外的要点。

如果您坚持使用 react-router-domv5 版本,您需要升级到 5.2.0,问题将得到解决,因为它是在 5.2.0 中引入的。


或者您可以升级到v6,使用useNavigate代替useHistory

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

const navigate = useNavigate();

navigate('/home');

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

const navigate = useNavigate();

const confirm = (e) => {
    navigate.push('/')
}

7
您的回答可以通过提供更多的支持性信息来改进。请编辑以添加更多详细信息,例如引证或文献,以便其他人可以确认您的回答是否正确。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
看起来这个不再起作用了,例如在v6上出现“不是一个函数”的错误。 - Jacob David C. Cunningham

5
在react-router-dom v6中,useHistory()函数被useNavigate()替换。
const navigate = useNavigate();
navigate("/login")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接