我在最新的应用程序中使用react router和redux,我面临着一些与基于当前url参数和查询所需状态更改相关的问题。
基本上,我有一个组件,需要在每次url更改时更新它的状态。状态是通过redux的道具传递给decorator的,就像这样
@connect(state => ({
campaigngroups: state.jobresults.campaigngroups,
error: state.jobresults.error,
loading: state.jobresults.loading
}))
目前,我正在使用componentWillReceiveProps生命周期方法来响应来自react-router的url更改,因为当this.props.params和this.props.query中的url更改时,react-router将向处理程序传递新的props-此方法的主要问题是,我在该方法中触发一个操作以更新状态-然后将新的道具传递给组件,组件将再次触发相同的生命周期方法-因此基本上创建了一个无休止的循环,目前我正在设置一个状态变量来阻止这种情况发生。
componentWillReceiveProps(nextProps) {
if (this.state.shouldupdate) {
let { slug } = nextProps.params;
let { citizenships, discipline, workright, location } = nextProps.query;
const params = { slug, discipline, workright, location };
let filters = this._getFilters(params);
// set the state accroding to the filters in the url
this._setState(params);
// trigger the action to refill the stores
this.actions.loadCampaignGroups(filters);
}
}
是否有基于路由转换触发操作的标准方法,或者我是否可以将存储的状态直接连接到组件的状态,而不是通过道具传递?我已经尝试使用WillTransition静态方法,但是我没有访问this.props.dispatch的权限。
如前所述,解决方案分为两部分:
为此,您所要做的就是设置react router redux。按照指示去做,你会没事的。
设置完所有内容后,您应该有一个路由
状态,如下所示:
在代码的某个地方,您现在应该有这样的东西:
// find this piece of code
export default function configureStore(initialState) {
// the logic for configuring your store goes here
let store = createStore(...);
// we need to bind the observer to the store <<here>>
}
您要做的是观察存储中的更改,以便在某些内容发生更改时分派
操作。
正如@deook提到的,您可以使用rx
,也可以编写自己的观察者:
reduxStoreObserver.js
var currentValue;
/**
* Observes changes in the Redux store and calls onChange when the state changes
* @param store The Redux store
* @param selector A function that should return what you are observing. Example: (state) => state.routing.locationBeforeTransitions;
* @param onChange A function called when the observable state changed. Params are store, previousValue and currentValue
*/
export default function observe(store, selector, onChange) {
if (!store) throw Error('\'store\' should be truthy');
if (!selector) throw Error('\'selector\' should be truthy');
store.subscribe(() => {
let previousValue = currentValue;
try {
currentValue = selector(store.getState());
}
catch(ex) {
// the selector could not get the value. Maybe because of a null reference. Let's assume undefined
currentValue = undefined;
}
if (previousValue !== currentValue) {
onChange(store, previousValue, currentValue);
}
});
}
现在,您所要做的就是使用我们刚刚编写的reduxStoreObserver.js来观察更改:
import observe from './reduxStoreObserver.js';
export default function configureStore(initialState) {
// the logic for configuring your store goes here
let store = createStore(...);
observe(store,
//if THIS changes, we the CALLBACK will be called
state => state.routing.locationBeforeTransitions.search,
(store, previousValue, currentValue) => console.log('Some property changed from ', previousValue, 'to', currentValue)
);
}
上面的代码使我们的函数在每次LocationBeforeTransformations.search状态发生更改时都被调用(这是用户导航的结果)。如果需要,可以观察que查询字符串等。
如果您希望由于路由更改而触发操作,则只需在处理程序内部执行store.dispatch(yourAction)
。
好吧,我最终在redux的github页面上找到了答案,所以我将在这里发布。希望它能帮别人省去一些痛苦。
@我认为这个问题有两个方面。首先,componentWillReceiveProps()不是响应状态更改的理想方式——主要是因为它迫使您必须思考,而不是像我们使用Redux那样被动思考。解决方案是将当前路由器信息(位置、参数、查询)存储在存储区内。然后,您的所有状态都位于同一位置,您可以使用与其余数据相同的reduxapi订阅它。
诀窍是创建一个动作类型,每当路由器位置发生变化时就会触发。这在即将发布的1.0版本的React路由器中很容易:
// routeLocationDidUpdate() is an action creator
// Only call it from here, nowhere else
BrowserHistory.listen(location => dispatch(routeLocationDidUpdate(location)));
现在,您的存储状态将始终与路由器状态同步。这解决了手动响应查询参数更改和上面组件中setState()的需要——只需使用Redux的连接器。
<Connector select={state => ({ filter: getFilters(store.router.params) })} />
问题的第二部分是,您需要一种对视图层之外的重复使用状态更改作出反应的方法,例如,对路由更改触发一个操作。如果愿意,您可以继续将componentWillReceiveProps用于您描述的简单案例。
不过,对于任何更复杂的问题,如果您愿意,我建议您使用RxJS。这正是可观测数据的设计目的——反应式数据流。
要在Redux中做到这一点,首先创建一个可观察的存储状态序列。您可以使用rx的可观察的FromStore()来实现这一点。
按CNP建议编辑
import { Observable } from 'rx'
function observableFromStore(store) {
return Observable.create(observer =>
store.subscribe(() => observer.onNext(store.getState()))
)
}
然后就是使用可观察的操作符来订阅特定的状态变化。以下是成功登录后从登录页面重新定向的示例:
const didLogin$ = state$
.distinctUntilChanged(state => !state.loggedIn && state.router.path === '/login')
.filter(state => state.loggedIn && state.router.path === '/login');
didLogin$.subscribe({
router.transitionTo('/success');
});
此实现比使用命令式模式(如componentDidReceiveProps())的相同功能简单得多。
问题内容: 我在最新的应用程序中使用react-router和redux,并且遇到了一些与基于当前url参数和查询所要求的状态更改有关的问题。 基本上,我有一个组件,每次URL更改时都需要更新其状态。像这样通过装饰器通过redux通过props传递状态 目前,我正在使用componentWillReceiveProps生命周期方法来响应来自react- router的url更改,因为当this.p
使用redux和反应路由器,我想访问路由指定的组件以外的组件上的路由参数。 我已经对react-router、redux和react-router-redux进行了如下设置,我想从我的redux存储访问reportId参数。 我已经尝试连接react-redux路由器来存储路由状态,但是我发现除了活动路由的完整路径之外,redux内部没有任何有用的存储。这让我可以选择从redux中的路径解析出re
我正在使用react路由器v4和redux,如果用户未登录,我想使用私有和受保护的路由重定向。 我有一个路由组件: 它是这样实现的: 这是私人路线: 传递prop的最佳方式是什么,如果我连接Routes组件并从那里传递是否可以,或者应该从其他地方传递,或者连接需要它的每个组件并从那里读取?此外,这种方法如何处理嵌套路由,如?谢谢
如果我将路由折叠起来,这样看起来就像: 工作很好。我嵌套的原因是因为我将在“dashboard”下有多个子项,并且希望它们都在URL中以为前缀。
我有一个简单的(目前)应用程序,使用react router和redux,我想为它添加国际化功能。 我已经安装了npm包,并且能够安装和运行提供的示例。我已经将适当的导入添加到我自己的应用程序中,并将国际化标签添加到根渲染方法中。 当我将I18nextProvider标记添加到render方法时,我得到了错误 找不到模块“react” 这并不是特别有用,尤其是因为如果我删除标签,react应用程序