react-router-dom子组件渲染<Link>提示未在BrowserRouter内的问题求解
问题解决方法
这个报错的核心原因是你要渲染的Link组件所在的React组件树,没有获取到路由提供者注入的context。即使你外层的父组件已经包裹了路由容器,如果你是通过ReactDOM.render单独渲染独立的React元素树来替换DOM,这部分新渲染的内容和外层的主应用组件树是完全隔离的,无法继承主应用的路由context,就会触发该错误。
方案1:使用React状态驱动渲染(推荐)
不要手动调用ReactDOM.render替换DOM元素,改为把排序后的数据存在组件state中,在组件的render方法中直接根据state渲染Link列表,这样所有元素都在同一个主组件树内,可以正常获取路由context。
代码示例:
import { Component } from 'react'; import { Link } from 'react-router'; class ListComponent extends Component { state = { sortedList: [] } // 数据排序逻辑 sortData = (rawData) => { const sorted = rawData.sort(/* 你的排序规则 */) this.setState({ sortedList: sorted }) } render() { return ( <div className="数据容器"> {this.state.sortedList.map(item => ( <Link to={`/detail/${item.id}`} key={item.id}> {item.name} </Link> ))} </div> ) } }
方案2:用编程式导航替代Link组件
如果你确实需要手动操作DOM渲染元素,可以不用Link组件,改为渲染普通的可点击元素,点击时调用路由提供的跳转方法实现导航:
首先给当前组件包裹withRouter高阶组件获取路由实例,然后绑定点击事件:
import { withRouter } from 'react-router'; class ListComponent extends Component { update = () => { const sortedList = /* 排序后的数组 */ const container = document.getElementById('你的容器ID') sortedList.forEach(item => { const itemEl = document.createElement('div') itemEl.innerText = item.name itemEl.onclick = () => { this.props.history.push(`/detail/${item.id}`) } container.appendChild(itemEl) }) } } export default withRouter(ListComponent)
方案3:为独立渲染的元素树注入路由context
如果必须单独渲染Link元素,你可以给要渲染的内容外层包裹一个路由上下文提供者,复用全局的history实例即可:
import ReactDOM from 'react-dom'; import { Router, browserHistory } from 'react-router'; ReactDOM.render( <Router history={browserHistory}> <Link to={`/detail/${item.id}`}>{item.name}</Link> </Router>, 你的目标DOM节点 )
额外注意事项
react-router v3中不存在BrowserRouter组件,该组件是v4及以后版本的API,如果你当前v3版本误用了BrowserRouter,请替换为Router配合browserHistory使用,否则会导致context传递异常。
内容的提问来源于stack exchange,提问作者Jonathan Kim
相关产品推荐
相关产品推荐

