如果我有这样的模型:
export interface User {
id: string;
email: string;
someOptional?: string;
}
并从api中获得2种结构:
{
id: 1,
email: x@l.com
}
和
{
id: 1,
email: x@l.com,
someOptional: "something"
}
商店目前具有第一种结构。 现在获取第二个结构将导致商店拉出第一个结构,而不是新的“扩展版本”,因为它已经(当然)已经有了它。
我该如何克服? 我需要创建一个新状态来保存扩展版本吗?
@PierreDuc发表评论: 我这样解决我的路线
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
Observable<Movie> {
const movieId = route.params['id'];
//WORKFLOW: ((6))
return this.store
.pipe(
select(selectMovieById(movieId)),
tap(movie => {
if (!movie) {
this.store.dispatch(new MovieRequested({movieId}));
}
}),
filter(movie => !!movie),
first()
)
}
,但selectMovieById(movieId)从商店返回的电影的属性比MovieRequested({movieId})少 因此,当我从/ movies移至电影/ 123时,我不会使用MovieRequested({movieId}) 但是如果我刷新电影/ 123,我将获得正确的数据,并且“电影”状态仅包含1个项目。
我应该将此扩展版本存储为“ currentMovie”状态吗?
@ХристиянХристов进行评论:
export const moviesRoutes: Routes = [
{
path: "",
component: HomeComponent
},
{
path: ':id',
component: MovieDetailsComponent,
resolve: {
movie: MovieResolver
}
}
];
解决方案:感谢@ХристиянХристов 在解析器中添加
this.store.dispatch(new MovieClear());
在开始时会起作用。对于那些想知道MovieClear减速器的人
case MoviesActionTypes.MovieClear:
return {
...state,
currentMovie: undefined
}
答案 0 :(得分:2)
对于类似的情况,我建议采用以下结构
let initialState = {
id: undefined,
email: undefined,
optional: undefined
}
这样,您将克服问题。
注意:
我假设现在您正在遇到一些未定义的相关错误,这是由于访问存储中的未初始化字段而引起的,但是即使现在optional
参数是某种对象,您仍然会得到错误(访问某些对象属性时)。我的建议是在流中进行一些过滤逻辑(查找rxjs过滤器运算符),或在模板中使用?
运算符。
好的,我想我现在遇到了您的问题。
首先:您必须在路径配置中添加runGuardsAndResolvers
,以便每次更改路由时都会触发解析器,该路径位于解析器或当前路径的左侧(例如,如果您选择更改参数,但保持相同的路径
第二:添加一个new MovieReset()
动作,目的是重置存储状态(换句话说,将其清除)
创建此类动作后,使用该动作的一种方法是将其分配到ngDestroy
的{{1}}钩子中,这将重置制作的电影,以便解析器每次返回新电影。时间被触发。
另一种方法几乎相同,但是可以在MovieDetailsComponent
钩子中使用它,而可以在解析器本身中重置存储,并通过onDestroy
(在分派reset操作之后)返回存储在商店中的新值。
答案 1 :(得分:0)
您可以发布用于“ MovieRequested”操作的Reducer吗?
在Reducer中,您可以返回先前状态,其中扩展了带有“ MovieLoaded”操作的新数据的扩展状态(或者您如何调用获取新电影数据的操作)。 这可能看起来像这样:
switch(action.type) {
case MovieActionTypes.MOVIE_LOADED: {
return {
...state,
movies: action.payload
}
}
该代码中的“ ...状态”被截断,告诉商店使用您以前的状态并将其扩展到下一部分(电影)。这样,您将获得如下所示的状态:
state = {
movies: [
{
id: 1,
email: x@l.com
},
{
id: 2,
email: x@2.com
}
],
...
如果这是您想要的(恕我直言,这是商店的目的,因此您保留了会话中请求的所有物品),则必须调整状态以使其可以容纳多部电影:
export interface State {
isLoading: boolean;
error: any;
movies: Array<Movie>;
...
}
export const initialMovieState: State = {
isLoading: false,
error: "",
movies: [{
id: 1,
email: x@1.com
}],
...
}