将 xhr 数据加载到 react redux 路由页面时的事件顺序是什么?
What are the sequence of events when loading xhr data into a react redux routed page?
我是一个 react/redux 菜鸟,让自己感到困惑。
这是我想要实现的:
/myapp/#/
- 全局导航 links 到 /myapp/#/ 和 /myapp/#/products
/myapp/#/products
- 全局导航(同上)
- 从 axios GET XHR 请求中检索到的产品列表。每个产品 links 到 /myapp/#/products/{productId}
/myapp/#/products/{productId}
- 全局导航(同上)
- 产品列表(如上)
- 产品详细信息面板,显示从另一个 axios GET XHR 请求中检索到的其他详细信息
用户应该能够单击列表中的产品以在插入的产品详细信息面板中查看详细信息,但不应重新请求列表 XHR 请求。
我的代码
/index.js
...
//I don't think this is the right place for this code...
function loadProductListData() {
store.dispatch(fetchListData('/api/products'))
}
render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={HomePage} />
<Route path="/products(/:productId)" component={ProductsPage} onEnter={loadProductListData} />
</Router>
</Provider>,
document.getElementById('root')
)
...
/components/menu.js
import React from 'react'
import { Link } from 'react-router';
const Menu = () => (
<ul>
<li><Link to={''}>Home</Link></li>
<li><Link to={'products'}>Products</Link></li>
</ul>
)
export default Menu
/components/productList.js
import React from 'react'
import { Link } from 'react-router';
class List extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<ul>
{
this.props.products.map(product =>
this.renderRow(product)
)
}
</ul>
)
}
renderRow (product) {
return (
<li key={product.id}><Link to={'products/' + product.id}>{product.name}</Link></li>
)
}
}
export default List
/actions.js
export const REQ_DATA = 'REQ_DATA';
export const RECV_DATA = 'RECV_DATA';
import axios from 'axios'
function requestData() {
return {type: types.REQ_DATA}
}
function receiveData(json) {
return{
type: types.RECV_DATA,
data: json
}
}
export function fetchListData(url) {
return function(dispatch) {
dispatch(requestData())
return axios({
url: url,
timeout: 20000,
method: 'get',
responseType: 'json'
})
.then(function(response) {
dispatch(receiveData(response.data))
})
.catch(function(response){
//
})
}
}
我上面的代码可以工作,但我现在纠结于下一步该怎么做。我不确定我是否应该在路由上使用 onEnter 来触发 XHR 请求,因为产品详细信息页面的 link 通过相同的路由,并为列表数据触发相同的 XHR。
我的问题
我是否应该使用触发 XHR、更新状态(导致组件重新渲染)然后手动推送到新路由的 onClick 处理程序,而不是使用 Link? link 简单地重新路由是否正确,是否可能由于路由而触发其他所有内容?正如我所说,我不想在重新路由时重新加载列表组件。
对于此类应用程序的方法和体系结构的任何其他一般性建议,我们将不胜感激。
您应该在 componentWillMount() 中分派 loadList 操作,并在您的 List 组件中实施 shouldComponentUpdate 回调,以根据您的状态控制该组件是否应该再次 rendered/updated。
例如:
shouldComponentUpdate(nextProps, nextState) {
return this.props.products !== nextProps.products;
}
查看 https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate
上的文档
然后在您的后端使用“301 - 未修改”headers,如果您的产品列表中没有任何更改,则不会总是 return 相同的数据。
要加载产品详细信息,您可以像这样在 componentWillReceiveProps 中发送详细信息加载操作:
componentWillReceiveProps(nextProps) {
if (this.props.params.id !== nextProps.params.id) {
this.props.dispatch(fetchDetailProduct(nextProps.params.id));
}
}
通过这种方式,您可以检查用户是否点击了不同的产品 ID。如果是这样,将调度加载此详细数据的操作。该组件将根据您的 redux 流程使用您的新产品详细信息数据进行更新。
作为架构方面的建议,我还建议您为操作取一个更好的名称,例如 'PRODUCT/FETCH_LIST'、'PRODUCT/FETCH_LIST_RECEIVED'、'PRODUCT/FETCH_LIST_ERROR'.
我还建议您使用 Immutable.js (https://facebook.github.io/immutable-js) 作为您所在的州。识别您所在州内的更新会容易得多,因为它为所有 objects 提供了一些有效的 equals() 检查。使用 Immutable.js 数据结构,您的 shouldComponentUpdate 将如下所示:
shouldComponentUpdate(nextProps, nextState) {
return !this.props.products.equals(nextProps.products);
}
我是一个 react/redux 菜鸟,让自己感到困惑。
这是我想要实现的:
/myapp/#/
- 全局导航 links 到 /myapp/#/ 和 /myapp/#/products
/myapp/#/products
- 全局导航(同上)
- 从 axios GET XHR 请求中检索到的产品列表。每个产品 links 到 /myapp/#/products/{productId}
/myapp/#/products/{productId}
- 全局导航(同上)
- 产品列表(如上)
- 产品详细信息面板,显示从另一个 axios GET XHR 请求中检索到的其他详细信息
用户应该能够单击列表中的产品以在插入的产品详细信息面板中查看详细信息,但不应重新请求列表 XHR 请求。
我的代码
/index.js
...
//I don't think this is the right place for this code...
function loadProductListData() {
store.dispatch(fetchListData('/api/products'))
}
render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={HomePage} />
<Route path="/products(/:productId)" component={ProductsPage} onEnter={loadProductListData} />
</Router>
</Provider>,
document.getElementById('root')
)
...
/components/menu.js
import React from 'react'
import { Link } from 'react-router';
const Menu = () => (
<ul>
<li><Link to={''}>Home</Link></li>
<li><Link to={'products'}>Products</Link></li>
</ul>
)
export default Menu
/components/productList.js
import React from 'react'
import { Link } from 'react-router';
class List extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<ul>
{
this.props.products.map(product =>
this.renderRow(product)
)
}
</ul>
)
}
renderRow (product) {
return (
<li key={product.id}><Link to={'products/' + product.id}>{product.name}</Link></li>
)
}
}
export default List
/actions.js
export const REQ_DATA = 'REQ_DATA';
export const RECV_DATA = 'RECV_DATA';
import axios from 'axios'
function requestData() {
return {type: types.REQ_DATA}
}
function receiveData(json) {
return{
type: types.RECV_DATA,
data: json
}
}
export function fetchListData(url) {
return function(dispatch) {
dispatch(requestData())
return axios({
url: url,
timeout: 20000,
method: 'get',
responseType: 'json'
})
.then(function(response) {
dispatch(receiveData(response.data))
})
.catch(function(response){
//
})
}
}
我上面的代码可以工作,但我现在纠结于下一步该怎么做。我不确定我是否应该在路由上使用 onEnter 来触发 XHR 请求,因为产品详细信息页面的 link 通过相同的路由,并为列表数据触发相同的 XHR。
我的问题 我是否应该使用触发 XHR、更新状态(导致组件重新渲染)然后手动推送到新路由的 onClick 处理程序,而不是使用 Link? link 简单地重新路由是否正确,是否可能由于路由而触发其他所有内容?正如我所说,我不想在重新路由时重新加载列表组件。
对于此类应用程序的方法和体系结构的任何其他一般性建议,我们将不胜感激。
您应该在 componentWillMount() 中分派 loadList 操作,并在您的 List 组件中实施 shouldComponentUpdate 回调,以根据您的状态控制该组件是否应该再次 rendered/updated。
例如:
shouldComponentUpdate(nextProps, nextState) {
return this.props.products !== nextProps.products;
}
查看 https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate
上的文档然后在您的后端使用“301 - 未修改”headers,如果您的产品列表中没有任何更改,则不会总是 return 相同的数据。
要加载产品详细信息,您可以像这样在 componentWillReceiveProps 中发送详细信息加载操作:
componentWillReceiveProps(nextProps) {
if (this.props.params.id !== nextProps.params.id) {
this.props.dispatch(fetchDetailProduct(nextProps.params.id));
}
}
通过这种方式,您可以检查用户是否点击了不同的产品 ID。如果是这样,将调度加载此详细数据的操作。该组件将根据您的 redux 流程使用您的新产品详细信息数据进行更新。
作为架构方面的建议,我还建议您为操作取一个更好的名称,例如 'PRODUCT/FETCH_LIST'、'PRODUCT/FETCH_LIST_RECEIVED'、'PRODUCT/FETCH_LIST_ERROR'.
我还建议您使用 Immutable.js (https://facebook.github.io/immutable-js) 作为您所在的州。识别您所在州内的更新会容易得多,因为它为所有 objects 提供了一些有效的 equals() 检查。使用 Immutable.js 数据结构,您的 shouldComponentUpdate 将如下所示:
shouldComponentUpdate(nextProps, nextState) {
return !this.props.products.equals(nextProps.products);
}