繁体   English   中英

如何在功能性 React JS 组件中获取数据?

[英]How to fetch data in a functional react JS component?

我正在开发一个 React JS、Redux、GraphQL、TypeScript 应用程序。

我想知道如何调用 function 从我的容器中获取数据并通过 GraphQL 更新 state。

通过 GraphQL 加载数据的动作名称为appActions.getAppData();

但它会导致无限刷新循环,因为它会触发 (StatusActions.startAppLoading()); 它也更新了 state。

我想知道如何解决此问题或如何将 /Main/index.tsx 重写为 class 组件并从 componentDidMount() 调用 startAppLoading()。

先感谢您。

应用结构

主要的.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { configureStore } from 'app/store';
import { Router } from 'react-router';
import { App } from './app';

// prepare store
const history = createBrowserHistory();
const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <App />
    </Router>
  </Provider>,
  document.getElementById('root')
);

应用程序/index.tsx

import React from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { App as Main } from 'app/containers/Main';
import { hot } from 'react-hot-loader';

let currentContainer = Main;

export const App = hot(module)(() => (
  <Switch>
    <Route exact path="/" component={currentContainer} />
    <Route path="*">
      <Redirect to="https://google.com" />
    </Route>
  </Switch>
));

应用程序/容器/Main/index.tsx

import React from 'react';
import style from './style.css';
import { RouteComponentProps } from 'react-router';
import { useDispatch, useSelector } from 'react-redux';
import { useTodoActions } from 'app/actions';
import { useAppActions } from 'app/actions';
import { RootState } from 'app/reducers';
import { Header, TodoList, Footer } from 'app/components';

export namespace App {
  export interface Props extends RouteComponentProps<void> {}
}

export const App = ({ history, location }: App.Props) => {
  const dispatch = useDispatch();
  const appActions = useAppActions(dispatch);

const { apps } = useSelector((state: RootState) => {
    return {
      apps: state.apps
    };
  });
  appActions.getAppData();

  return (
    <div className={style.normal}>
      <Header />
      <TodoList appActions={appActions} apps={apps} />
      <Footer />
    </div>
  );
};

应用程序/动作/apps.ts

export const getAppData = () => {
    let appKey = 'interpegasus';
    return (dispatch: Dispatch) => {
      dispatch(StatusActions.startAppLoading());
      debugger;
      apolloClient
        .query({
          query: gql`
            query getApp($appKey: String!) {
              getApp(id: $appKey) {
                id
                name
                domain
              }
            }
          `,
          variables: {
            appKey: appKey
          }
        })
        .then((result) => {
          debugger;
          if (result.data.apps.length > 0) {
            dispatch(populateAppData(result.data.apps[0]));
          }
          dispatch(StatusActions.endAppLoading());
        })
        .catch((error) => {
          dispatch(StatusActions.endAppLoading());
          console.log({
            error: error
          });
        });
    };
  };

你应该把你的appActions.getAppData()像这样放在useEffect钩子中

useEffect(()=>{

 appActions.getAppData()

},[])

查看官方文档介绍 Hooks

Main/index.tsx中,您正在调用appActions.getAppData(); 这将引导您到actions/apps.ts 在这里,您正在执行dispatch(StatusActions.startAppLoading()); 这将更新 state 并重新渲染“Main/index.tsx”。 然后再次调用 getAppData() 并且循环继续导致无限循环。

仅在未loading时调用 api。

像这样的东西:

  ...
  const { apps, loading } = useSelector((state: RootState) => {
    return {
      apps: state.apps,
      loading: state.loading // <----- replace with your actual name of your state 
    };
  });

  if(!loading){
    appActions.getAppData();
  }
  ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM