ReactJS 中的路由行为不当
Routing misbehaving in ReactJS
我有一个组件可以调用 AJAX 来获取一些数据。此后通过for循环处理,创建数组如下:
var path = '/clinic/'+d.id;
res.push(
<Tappable className='clinic' onTap={() => router.transitionTo(path, i)}>
<div id='name'>{d.name}</div>
<div>{d.address}</div>
<div>{ms}</div>
<span>Timings: {d.timings.value_formatted} - {d.timings.value2_formatted}</span>
</Tappable>
);
除 link 之外的所有数据均正确呈现。数组中的所有项目都link编辑为数组中最后一项的 ID。
例如
如果有 10 个 ID 为 1-10 的项目,理想情况下项目应该 link 到 clinic/1、clinic/2 等。但是,所有项目都被路由到 clinic/10.
路由定义如下:
import './theme';
import { router, route } from 'reapp-kit';
router(require,
route('home', '/',
route('clinics'),
route('Clinic', 'clinic/:id'),
route('search')
)
);
这是完整的文件:https://gist.github.com/fotuzlab/6e5ef4c98db678190d98
在我看来很经典"for loop closure problem"。由于变量在 Javascript 中具有函数范围,因此您的 path
和 i
变量实际上是每次迭代的相同变量。为您的 onTap
匿名函数处理程序创建了一个闭包,因此每个匿名函数都从它们的闭包中引用相同的变量,这些变量将在循环结束后将最后的值分配给变量。
您可以通过使用立即调用的函数表达式 (IIFE) 来解决此问题,该函数表达式将每个唯一值绑定到循环中每次迭代的新变量(IIF 的参数),如下所示:
onTap={((iPath, j) => () => router.transitionTo(iPath, j))(path, i)}
或者如果有可能使用 ES6(如果您正在使用 Babel.js 或其他一些转译器,或者只关心支持兼容的浏览器),您可以使用新的 let
关键字来提供变量块作用域而不是函数作用域,如下所示:
for (let i = 0; i < this.state.clinics.count; i++) {
var ms = '';
d = this.state.clinics.data[i];
if (d.medical_scheme) {
$.map(d.medical_scheme, function(val, i){
ms += val.label + ' ';
});
}
let path = '/clinic/'+d.id;
res.push(
<Tappable className='clinic' onTap={() => router.transitionTo(path, i)}>
<div id='name'>{d.name}</div>
<div>{d.address}</div>
<div>{ms}</div>
<span>Timings: {d.timings.value_formatted} - {d.timings.value2_formatted}</span>
</Tappable>
);
}
我有一个组件可以调用 AJAX 来获取一些数据。此后通过for循环处理,创建数组如下:
var path = '/clinic/'+d.id;
res.push(
<Tappable className='clinic' onTap={() => router.transitionTo(path, i)}>
<div id='name'>{d.name}</div>
<div>{d.address}</div>
<div>{ms}</div>
<span>Timings: {d.timings.value_formatted} - {d.timings.value2_formatted}</span>
</Tappable>
);
除 link 之外的所有数据均正确呈现。数组中的所有项目都link编辑为数组中最后一项的 ID。
例如
如果有 10 个 ID 为 1-10 的项目,理想情况下项目应该 link 到 clinic/1、clinic/2 等。但是,所有项目都被路由到 clinic/10.
路由定义如下:
import './theme';
import { router, route } from 'reapp-kit';
router(require,
route('home', '/',
route('clinics'),
route('Clinic', 'clinic/:id'),
route('search')
)
);
这是完整的文件:https://gist.github.com/fotuzlab/6e5ef4c98db678190d98
在我看来很经典"for loop closure problem"。由于变量在 Javascript 中具有函数范围,因此您的 path
和 i
变量实际上是每次迭代的相同变量。为您的 onTap
匿名函数处理程序创建了一个闭包,因此每个匿名函数都从它们的闭包中引用相同的变量,这些变量将在循环结束后将最后的值分配给变量。
您可以通过使用立即调用的函数表达式 (IIFE) 来解决此问题,该函数表达式将每个唯一值绑定到循环中每次迭代的新变量(IIF 的参数),如下所示:
onTap={((iPath, j) => () => router.transitionTo(iPath, j))(path, i)}
或者如果有可能使用 ES6(如果您正在使用 Babel.js 或其他一些转译器,或者只关心支持兼容的浏览器),您可以使用新的 let
关键字来提供变量块作用域而不是函数作用域,如下所示:
for (let i = 0; i < this.state.clinics.count; i++) {
var ms = '';
d = this.state.clinics.data[i];
if (d.medical_scheme) {
$.map(d.medical_scheme, function(val, i){
ms += val.label + ' ';
});
}
let path = '/clinic/'+d.id;
res.push(
<Tappable className='clinic' onTap={() => router.transitionTo(path, i)}>
<div id='name'>{d.name}</div>
<div>{d.address}</div>
<div>{ms}</div>
<span>Timings: {d.timings.value_formatted} - {d.timings.value2_formatted}</span>
</Tappable>
);
}