我正在尝试在 React 上使用带有 GraphQLconst sliceQuery = useQuery(ALL_SLICES)
的 redux,但由于 GraphQL 钩子及其承诺Object { data: {}, variables: {}, refetch: (), fetchMore: (), updateQuery: (), startPolling: (), stopPolling: (), subscribeToMore: (), loading: true, networkStatus: 1, … }
,我似乎无法使用 useEffect 来最小化渲染。因此,我被迫在 useEffect 之外更新props.slices
,因为我必须等待 GraphQL 钩子完成加载
if (!sliceQuery.loading && props.slices === null) {
const allSlices = sliceQuery.data.allSlices
props.initializeSlices(allSlices)
props.setCurrentSlice(allSlices.find(s => s._id === splitUrl[5]))
}
这是我完整的App.js组件:
import React, { useEffect } from 'react'
import { initializeSlices } from './reducers/sliceReducer'
import { setCurrentSlice } from './reducers/currentSliceReducer'
import { connect } from 'react-redux'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import { useQuery } from '@apollo/react-hooks'
import NavBar from './components/navBar/NavBar'
import Slice from './components/pages/Slice'
import About from './components/pages/About'
import Policies from './components/pages/Policies'
import Contact from './components/pages/Contact'
import './static/css/base.css'
import { ALL_SLICES } from './schemas'
const App = (props) => {
console.log('App.js is ran')
const sliceQuery = useQuery(ALL_SLICES)
const splitUrl = window.location.href.split('/')
if (!sliceQuery.loading && props.slices === null) {
const allSlices = sliceQuery.data.allSlices
props.initializeSlices(allSlices)
props.setCurrentSlice(allSlices.find(s => s._id === splitUrl[5]))
}
const getSliceById = (id) => {
return props.slices.find(s => s._id === id)
}
if (!props.slices || !props.currentSlice) {
return (
<div>
<h1>loading..</h1>
</div>
)
}
return (
<div className="wrapper">
<Router>
<NavBar />
<Route exact path="/" render={() => <Slice slice={getSliceById('5e2db26efa3d070ec879b0e9')} /> } />
<Route path="/slice/:name/:id" render={({match}) => <Slice slice={getSliceById(match.params.id)} /> } />
<Route path="/about" render={() => <About /> } />
<Route path="/policies" render={() => <Policies /> } />
<Route path="/contact" render={() => <Contact /> } />
</Router>
</div>
);
}
const mapStateToProps = (state) => {
return {
slices: state.slices,
currentSlice: state.currentSlice,
}
}
export default connect(
mapStateToProps,
{ initializeSlices, setCurrentSlice }
)(App)
以下是页面加载的控制台日志:
开发服务器已断开连接。 如有必要,请刷新页面。
[HMR] 正在等待来自 WDS 的更新信号...
应用.js正在运行
./src/App.js 第 1:17 行:"useEffect"已定义,但从未使用 no-un-used-va
警告:渲染方法应该是 props 和状态的纯函数;不允许从渲染触发嵌套组件更新。如有必要,请在组件 DidUpdate 中触发嵌套更新。 检查应用程序的渲染方法。
应用.js正在运行
应用.js正在运行
应用.js正在运行
您仍然可以使用useEffect
仅在数据可用时执行方法。
const allSlices =
!sliceQuery.loading && props.slices === null
? sliceQuery.data.allSlices
: null;
useEffect(() => {
if(allSlices !== null) {
props.initializeSlices(allSlices)
props.setCurrentSlice(allSlices.find(s => s._id === splitUrl[5]))
}
}, [allSlices, props.initializeSlices, props.setCurrentSlice])
这只会调用方法props.initializeSlices
,并在allSlices
可用时props.setCurrentSlice
。
如果这些方法也是在渲染时创建的,则可能需要使用创建它们useCallback
来阻止它们触发要在后续渲染上执行的useEffect
挂钩。