Redux Toolkit linting 悖论
Posted
技术标签:
【中文标题】Redux Toolkit linting 悖论【英文标题】:Redux Toolkit linting paradox 【发布时间】:2021-08-07 04:44:23 【问题描述】:我在文件searchSlice.js
中定义了一个 Redux Toolkit 切片,它负责查询 API 并将响应数据存储在 store 的 state 中。目前看起来是这样的:
import createSlice, createAsyncThunk from '@reduxjs/toolkit';
import axios from 'axios';
const initialState =
query: '',
status: 'idle',
movies: [],
totalResults: null,
;
// Create slice
export const searchSlice = createSlice(
name: 'search',
initialState,
reducers:
updateQuery: (state, action) =>
state.query = action.payload;
,
,
extraReducers: (builder) =>
builder
.addCase(getMovies.pending, (state) =>
state.status = 'pending';
)
.addCase(getMovies.fulfilled, (state, action) =>
state.status = 'idle';
state.movies = action.payload.results;
state.totalResults = action.payload.total_results;
);
,
);
// Actions
export const updateQuery = searchSlice.actions;
// Reducers
export default searchSlice.reducer;
// Selectors
export const selectQuery = (state) => state.search.query;
export const selectStatus = (state) => state.search.status;
export const selectAllMovies = (state) => state.search.movies;
export const selectTotalResults = (state) => state.search.totalResults;
// Thunks
export const getMovies = createAsyncThunk(
'search/getMovies',
async (payload, store) =>
if (!store.getState().search)
dispatchEvent(updateQuery(payload));
try
console.log('payload: ', payload);
const res = await axios.get(`/search?query=$store.getState().search`);
return res.data;
catch (err)
return err;
);
正如我所见,除了导出实际的切片对象本身之外,您还必须导出其必要和附带的组件:
操作 减速机 选择器 谢谢由于上述组件高度耦合和相互依赖的性质,ESLint 将根据 searchSlice.js
文件中组件的顺序(按行号)抛出不同的 linting 错误。比如上面的代码sn-p,linting的错误是:
'getMovies' was used before it was defined. eslint(no-use-before-define)
如果我们尝试通过将 getMovies
函数声明重新排列到调用上方来修复错误,如下所示:
// ...
// Thunks
export const getMovies = createAsyncThunk(
'search/getMovies',
async (payload, store) =>
if (!store.getState().search)
dispatchEvent(updateQuery(payload));
try
console.log('payload: ', payload);
const res = await axios.get(`/search?query=$store.getState().search`);
return res.data;
catch (err)
return err;
);
// ...
// Create slice
export const searchSlice = createSlice(
name: 'search',
initialState,
reducers:
updateQuery: (state, action) =>
state.query = action.payload;
,
,
extraReducers: (builder) =>
builder
.addCase(getMovies.pending, (state) =>
state.status = 'pending';
)
.addCase(getMovies.fulfilled, (state, action) =>
state.status = 'idle';
state.movies = action.payload.results;
state.totalResults = action.payload.total_results;
);
,
);
// ...
然后我们得到相同的 linting 错误,但函数定义不同:
'updateQuery' was used before it was defined. eslint(no-use-before-define)
似乎不管文件的排列方式如何,ESLint 都会抛出一个自相矛盾的no-use-before-define
错误。
是否有不涉及更改 ESLint 规则的解决方案?有没有更好的方法来构建代码?我已经尝试将其拆分为更小的文件,但由于随附切片功能的高度相互依赖性质,ESLint 将开始抛出 import/no-cycle
错误,因为两个文件都需要相互导入内容。
作为一个附加问题,提升在这里如何发挥作用?
【问题讨论】:
【参考方案1】:当你处理一个循环时,你需要弄清楚哪个是有意义的依赖,哪个是依赖。在这种情况下,从 thunk 中删除 reducer 比从 reducer 中删除 thunk 更容易。
您可以通过从 thunk 中删除额外的已调度 updateQuery
操作并在您的 reducer 中处理该逻辑来修复依赖关系。您可以通过action.meta.arg
属性从getMovies.pending
case reducer 中的thunk 访问(名称混淆)payload
变量,该属性包含您调用thunk 操作创建者时使用的参数。
export const getMovies = createAsyncThunk(
'search/getMovies',
async (query) =>
const res = await axios.get(`/search?query=$query`);
return res.data;
// Don't catch errors here. Let them be thrown and handled by the 'rejected' action.
);
export const searchSlice = createSlice(
name: 'search',
initialState,
reducers:
// you might not even need this anymore, unless you use it elsewhere.
updateQuery: (state, action) =>
state.query = action.payload;
,
,
extraReducers: (builder) =>
builder
.addCase(getMovies.pending, (state, action) =>
// Update the query property of the state.
state.query = action.meta.arg;
state.status = 'pending';
)
.addCase(getMovies.fulfilled, (state, action) =>
state.status = 'idle';
state.movies = action.payload.results;
state.totalResults = action.payload.total_results;
);
,
);
顺便说一句,条件if (!store.getState().search)
没有意义。那将检查整个切片是否真实,它总是如此。
【讨论】:
以上是关于Redux Toolkit linting 悖论的主要内容,如果未能解决你的问题,请参考以下文章
如何实现redux-toolkit和next,js又不丢s-s-r
从 React Native Text Input 向 Redux Toolkit 的 createApi 添加动态数据?
Redux-Toolkit createAsyncThunk with Typescript