React Router 4 无法在具有 <Link> 的同一组件上加载新内容
React Router 4 can not load new content on same component with <Link>
当我点击 link 导致页面加载完全相同的组件时,我似乎无法触发除 render() 之外的任何其他 React 组件生命周期方法,即使 url 是不同的。所以这是我的代码
//index.js - the entry point
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import Config from './Settings/Config';
import App from './Components/App';
const c = new Config();
render(
<BrowserRouter basename={c.routerBaseName}>
<App />
</BrowserRouter>
, document.getElementById('root'));
这是我的应用程序 JS
// Components/App.js
import React, {Component} from 'react';
import {Route} from 'react-router-dom';
import BlogEntry from './BlogEntry';
export default class App extends Component {
render() {
console.log('app');
return (
<div>
<Route exact path="/blog/:name" component={BlogEntry} />
</div>
)
}
}
这是我的 BlogEntry.js
// Components/BlogEntry.js
import React from 'react';
import { Link } from 'react-router-dom';
export default class BlogEntry extends React.Component {
async componentDidMount() {
const [r1] = await Promise.all([
fetch(`http://api.myservice.com/${this.props.match.params.name}`)
]);
this.setState({content:await r1.json()});
console.log('fetch');
}
render() {
console.log('render');
if(!this.state) return <div></div>;
if(!this.state.content) return <div></div>;
const content = this.state.content;
return (
<div id="blog-entry" className="container">
<h1>{content.title}</h1>
<div dangerouslySetInnerHTML={{__html:content.content}}></div>
<div className="related-other">
<h2>Related Content</h2>
<ul>
<li><Link to="/blog/new-york-wins-the-contest">New York Wins the Contest!</Link></li>
<li><Link to="/blog/toronto-with-some-tasty-burgers">Toronto with Some Tasty Burgers</Link></li>
</ul>
</div>
</div>
);
}
}
所以发生的事情是,当我点击 Toronto with Some Tasty Burgers
或 New York Wins the Contest!
的 link 时,我看到网络浏览器地址栏中的 url 相应更新。但是我的 componentDidMount 没有触发。因此没有获取或加载新内容。
React 也不会让我将 onPress
事件处理程序放入 <Link>
对象。即使我这样做了,如果我要创建自己的 onpress 事件处理程序来加载页面,那么在浏览器单击后退按钮时管理历史状态将是一场噩梦。
所以我的问题是,如何才能让点击其中一个 link 实际上导致组件获取新数据并重绘并且成为浏览器后退按钮历史记录的一部分?
我将其添加到我的 BlogEntry.js,现在一切正常:
componentWillReceiveProps(nextProps) {
this.props = nextProps;
}
我认为您通过 componentWillReceiveProps(已弃用)提出的解决方案不够好。这是一个黑客。
你为什么不在状态中保留路由 ID(如 /blog/:id)。
然后是这样的:
componentDidUpdate() {
const { match: { params: { id: postId } = {} } } = this.props;
if(this.state.postId !== postId) {
// fetch content
}
}
当我点击 link 导致页面加载完全相同的组件时,我似乎无法触发除 render() 之外的任何其他 React 组件生命周期方法,即使 url 是不同的。所以这是我的代码
//index.js - the entry point
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import Config from './Settings/Config';
import App from './Components/App';
const c = new Config();
render(
<BrowserRouter basename={c.routerBaseName}>
<App />
</BrowserRouter>
, document.getElementById('root'));
这是我的应用程序 JS
// Components/App.js
import React, {Component} from 'react';
import {Route} from 'react-router-dom';
import BlogEntry from './BlogEntry';
export default class App extends Component {
render() {
console.log('app');
return (
<div>
<Route exact path="/blog/:name" component={BlogEntry} />
</div>
)
}
}
这是我的 BlogEntry.js
// Components/BlogEntry.js
import React from 'react';
import { Link } from 'react-router-dom';
export default class BlogEntry extends React.Component {
async componentDidMount() {
const [r1] = await Promise.all([
fetch(`http://api.myservice.com/${this.props.match.params.name}`)
]);
this.setState({content:await r1.json()});
console.log('fetch');
}
render() {
console.log('render');
if(!this.state) return <div></div>;
if(!this.state.content) return <div></div>;
const content = this.state.content;
return (
<div id="blog-entry" className="container">
<h1>{content.title}</h1>
<div dangerouslySetInnerHTML={{__html:content.content}}></div>
<div className="related-other">
<h2>Related Content</h2>
<ul>
<li><Link to="/blog/new-york-wins-the-contest">New York Wins the Contest!</Link></li>
<li><Link to="/blog/toronto-with-some-tasty-burgers">Toronto with Some Tasty Burgers</Link></li>
</ul>
</div>
</div>
);
}
}
所以发生的事情是,当我点击 Toronto with Some Tasty Burgers
或 New York Wins the Contest!
的 link 时,我看到网络浏览器地址栏中的 url 相应更新。但是我的 componentDidMount 没有触发。因此没有获取或加载新内容。
React 也不会让我将 onPress
事件处理程序放入 <Link>
对象。即使我这样做了,如果我要创建自己的 onpress 事件处理程序来加载页面,那么在浏览器单击后退按钮时管理历史状态将是一场噩梦。
所以我的问题是,如何才能让点击其中一个 link 实际上导致组件获取新数据并重绘并且成为浏览器后退按钮历史记录的一部分?
我将其添加到我的 BlogEntry.js,现在一切正常:
componentWillReceiveProps(nextProps) {
this.props = nextProps;
}
我认为您通过 componentWillReceiveProps(已弃用)提出的解决方案不够好。这是一个黑客。 你为什么不在状态中保留路由 ID(如 /blog/:id)。
然后是这样的:
componentDidUpdate() {
const { match: { params: { id: postId } = {} } } = this.props;
if(this.state.postId !== postId) {
// fetch content
}
}