【发布时间】:2020-03-26 16:05:35
【问题描述】:
我正在尝试将我的所有源代码从使用 react with redux 更改为 react-hook with redux 并将其与 firebase 连接:
当我重定向到 localhost:3000/blogs 时出现此警告,
index.js:1375 Warning: Maximum update depth exceeded. This can happen when a
component calls
setState inside useEffect, but useEffect either doesn't have a dependency
array, or one of the
dependencies changes on every render.
in BlogDashboard (created by Context.Consumer)
in Route (at App.jsx:32)
in Switch (at App.jsx:31)
in div (created by Container)
in Container (at App.jsx:30)
in Route (at App.jsx:27)
in App (at src/index.js:44)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:40)
in ReduxFirestoreProvider (created by ReactReduxFirebaseProvider)
in ReactReduxFirebaseProvider (at src/index.js:39)
in Provider (at src/index.js:38)
在 Index.js 中:
ReactDOM.render(
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}> // firebase worked fine
<BrowserRouter>
<ReduxToastr timeOut={2000} preventDuplicates position="bottom-right"
transitionIn="fadeIn" transitionOut="fadeOut" />
<App />
</BrowserRouter>
</ReactReduxFirebaseProvider>
</Provider>,
document.getElementById('root');
);
在 App.jsx 中:
const App = () => {
const auth = useSelector(state => state.firebase.auth, []);
if(!auth.isLoaded && auth.isEmpty) return <LoadingComponent />
return (
<Fragment>
<ModalManager />
<Switch>
<Route exact path='/' component={HomePage}/>
</Switch>
<Route path='/(.+)' render={() => (
<Fragment>
<NavBar />
<Container className="main">
<Switch>
<Route exact path='/blogs' component={BlogDashboard} />
<Route path='/blogs/:id' component={BlogDetailedPage} />
</Switch>
</Container>
</Fragment>
)}
/>
</Fragment>
);
}
在 BlogDashboard.jsx 中:
const BlogDashboard = () => {
const dispatch = useDispatch();
const firestore = useFirestore();
const blogs = useSelector(state => CastToArray(state.firestore.data.blogs) || []);//this worked fine
const moreBlogs = useSelector(state => state.blogs.moreBlogs);
const loading = useSelector(state => state.async.loading);
useEffect(() => {
const getBlogs = async () => {
await dispatch(getPagedBlogs({firestore}));
};
if(blogs.length === 0) {
getBlogs();
} else {
}
}, [dispatch, firestore, blogs]);
const handleGetNextBlogs = async () => {
await dispatch(getPagedBlogs({firestore}));
};
return (
<Grid>
<Grid.Column width={10}>
<BlogList blogs={blogs} loading={loading} moreBlogs ={moreBlogs} getNextBlogs=
{handleGetNextBlogs} />
</Grid.Column>
<Grid.Column width={10}>
<Loader active={loading} />
</Grid.Column>
</Grid>
);
};
export default BlogDashboard;
在 BlogActions 中:
export const getPagedBlogs = ({firestore}) =>
async (dispatch, getState) => {
dispatch(StartAction());
const LIMIT = 5;
let nextBlog = null;
const {firestore: {data: {blogs: items}}} = getState();
if (items && Object.keys(items).length >= LIMIT) {
let itemsArray = objectToArray(items);
nextBlog = await firestore.collection('blogs').doc(itemsArray[itemsArray.length -
1].id).get();
}
let query = await firestore.get({
collection: 'blogs',
limit: LIMIT,
where: ['date', '<=', new Date()],
startAfter: nextBlog,
storeAs: 'blogs'
});
if(query.docs.length < LIMIT) {
dispatch({type: MORE_BLOGS});
}
dispatch(FinishAction());
};
在 BlogReducer.js 中:
const initialState = {
blogs: [],
moreBlogs: true,
};
export const moreBlogs = (state) => {
return {
...state.blogs,
moreBlogs: true
}
}
export default createReducer(initialState, {
[MORE_BLOGS]: moreBlogs
});
在 BlogList.jsx 中:
const BlogList = ({blogs, moreBlogs, getNextBlogs, loading}) =>
<Fragment>
{blogs && blogs.length !== 0 &&
//Load blogs, using 'react-scroll-infinite'.
<InfiniteScroll pageStart={0} loadMore={getNextBlogs} hasMore=
{!loading && moreBlogs} initialLoad={false}>
{blogs && blogs.map(blog => (
<BlogListItem key={blog.id} blog={blog} />
))}
</InfiniteScroll>
}
</Fragment>
export default BlogList;
我明白警告的意思,但对 react hook 没有太多经验。
【问题讨论】:
-
好像你在渲染方法里面做 setState 。尝试在渲染之外使用 setState
-
你在哪里设置状态?您提供的代码都没有显示您在哪里使用 Firestore 数据并将其设置为状态。我假设这是在
BlogList内。请告诉我们您在哪里使用setState -
@JoshPittman,谢谢你提醒我,我更新了我的帖子。目前我没有在 react 中使用任何 setState 方法,我只是在 blogReducer 中创建了一个 intialState 并且 blogs 是一个空数组。
-
我使用“const blogs = useSelector(...)”从 Firestore 获取数据,在 BlogDashboard.jsx 中声明,博客列表运行良好
-
太棒了。请接受下面添加的答案,以帮助遇到类似问题的其他人。
标签: reactjs firebase google-cloud-firestore react-hooks