-1

我正在尝试 const sliceQuery = useQuery(ALL_SLICES)在 React 上将 redux 与 GraphQL 一起使用,但由于 GraphQL 钩子及其承诺,我似乎无法使用 useEffect 来最小化渲染Object { data: {}, variables: {}, refetch: (), fetchMore: (), updateQuery: (), startPolling: (), stopPolling: (), subscribeToMore: (), loading: true, networkStatus: 1, … }。因此,我不得不在props.slicesuseEffect 之外进行更新,因为我必须等待 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 的更新信号...

App.js 运行

./src/App.js 第 1:17 行:'useEffect' 已定义但从未使用 no-unused-va

警告:渲染方法应该是 props 和 state 的纯函数;不允许从渲染触发嵌套组件更新。如有必要,在 componentDidUpdate 中触发嵌套更新。检查 App 的渲染方法。

App.js 运行

App.js 运行

App.js 运行

4

1 回答 1

0

当您的数据可用时,您仍然可以使用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以及props.setCurrentSlice何时allSlices可用。

如果这些方法也是在渲染时创建的,您可能需要使用useCallback它们的创建位置来阻止它们触发useEffect挂钩以在后续渲染上执行。

于 2020-02-04T19:37:38.633 回答