我正在尝试确定我是否使用RTKQuery来保持Stencil.js组件的状态与DB正确同步。
我的行为是,我的组件将使用RTK查询和store.dispatch()获取数据,并将其分配给本地状态,然后用户改变组件,这也是使用rtk查询API通过storedispatch()函数发出的请求。
我设法让组件重新呈现的唯一方法是使用componentWIllLoad()
生命周期方法订阅存储并传入一个fetch函数store.dispatch(api.endpoints.fetchFunction.initiate())
作为回调。
虽然这可以很好地保持状态同步,但它确实会在fetchFunction()(作为操作调度并调用订阅)和fetchFunction()(调用fetchFunction())之间造成无限的调用循环,以此类推。这可以通过订阅中的一个简单console.log()语句看到。
虽然这种行为不是世界末日,但感觉并不优雅。是否可以改进?
RTK查询设置:我有一个API:
- api.ts
export const oracleApi = createApi({
reducerPath: 'oracleApi',
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:8000/api/v1/',
prepareHeaders: async headers => {
try {
console.log(await localForage.getItem('CHLJWT'))
const token = await getToken(localForage)
if (token) {
headers.set('Authorization', `CHLJWT ${token.access}`)
}
console.log('HEADERS Authorization: ', headers.get('Authorization'))
return headers
} catch (error) {
console.error('Login Required: ', error)
}
},
}),
tagTypes: ['Spaces', 'Auth', 'Users', 'Documents', 'Figures', 'Organisations'],
endpoints: build => ({
//Auth
login: build.mutation<CHLTokenData, CHLLoginData>({
query(body) {
return {
url: `auth/jwt/create/`,
method: 'POST',
body,
}
},
invalidatesTags: [{ type: 'Auth', id: 'LIST' }],
}),
一个还原商店:
- store.ts
export const store = configureStore({
reducer: {
// Add the generated reducer as a specific top-level slice
[api.reducerPath]: api.reducer,
},
// Adding the api middleware enables caching, invalidation, polling,
// and other useful features of `rtk-query`.
middleware: getDefaultMiddleware => getDefaultMiddleware().concat(api.middleware),
})
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)
和一个index.ts文件来合并它们
-index.ts
export const api = {
//Spaces
getSpace: async (id: SpaceId) => {
try {
const space = await store.dispatch(api.endpoints.getSpace.initiate(id))
return space
} catch (error) {
console.error(error)
}
},
getSpaces: async (data?) => {
try {
const spaces = await store.dispatch(api.endpoints.getSpaces.initiate())
return spaces
} catch (error) {
console.error(error)
}
},
deleteSpace: async (id: SpaceId) => {
try {
await store.dispatch(api.endpoints.deleteSpace.initiate(id))
} catch (error) {
console.error(error)
}
},
createSpace: async data => {
try {
const res = await store.dispatch(api.endpoints.addSpace.initiate(data))
return res
} catch (error) {
console.error(error)
}
},
updateSpace: async (space, data) => {
try {
const id = space.id
const res = await store.dispatch(api.endpoints.updateSpace.initiate({ id, ...data }))
return res
} catch (error) {
console.error(error)
}
},
}
最后,我有一个stencil.js组件
import { store } from 'server_state/store'
import { api } from 'server_state/index'
@Component({
tag: 'app-topbar',
styleUrl: 'app-topbar.css',
})
export class AppTopbar {
private unsubscribe: () => void
@State() space: Space
async componentWillLoad() {
this.spaceId = Router.activePath.slice(8, 44) as SpaceId
this.unsubscribe = store.subscribe(async () => {
await this.loadData()
})
await this.loadData()
}
disconnectedCallback() {
this.unsubscribe()
}
async loadData() {
try {
console.log('Loading data:app-topbar')
api.getSpace(this.spaceId)
this.space = spaceResult.data
} catch (error) {
console.error(error)
}
}
render() {
///
}
}
沿着改进此模式,我还特别感兴趣的是,是否可以使用redux中的createApi来获取数据,而无需调用store.subscribe()回调函数。
谢谢!
1条答案
按热度按时间chhqkbe11#
这实际上分为3个问题:
对于前两个主题,请参阅我的博客文章The History and Implementation of React-Redux和talk A Deep Dive into React-Redux中的详细解释,但TL;DR可参见我们的文档,网址为https://redux.js.org/tutorials/fundamentals/part-5-ui-react#integrating-redux-with-a-ui:
对于React,我们将所有逻辑封装在React-Redux包和
useSelector
钩子(以及旧的connect
Package 器)中。RTK Query的React钩子(如useGetPokemonQuery
)构建在其之上。对于Stencil,你需要从使用React-Redux的等价物开始,我看到已经有一个Stencil文档页面在https://stenciljs.com/docs/stencil-redux上讨论使用Redux,并且有一个
@stencil/redux
包。像Redux和RTK的其他部分一样,RTK Query也是UI不可知的。所以,你可以在没有React的情况下使用它,但是你必须做更多的工作。
我们在文档中介绍了一些关键信息:
在本例中,您可能希望生成一个沿着
const selector = api.endpoints.getPokemon.select("pikachu")
的端点选择器,并将其传递给Stencil Package 器mapStateToProps
,以便从存储中选择该数据。假设@stencil/redux
执行了我认为它执行的操作,则 * 应该 * 触发组件中的更新。