React:如何停止重新渲染组件或更改同一路由的路由器上的API调用 [英] React : How to stop re-rendering component or making an API calls on router change for the same route

查看:111
本文介绍了React:如何停止重新渲染组件或更改同一路由的路由器上的API调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要帮助,以停止在更改路线时再次进行相同的API调用.我试图在Web上和stackoverflow上找到可用的解决方案,但我无法弄清楚需要进行哪些更改来解决此问题.

I need help to stop making same API calls again on route change. I tried to find the solution available on the web and on stackoverflow, but I am not able to figure out what changes require to fix this thing.

我还尝试使用sessionStorage存储一个标志,如果触发了API调用,则将标志设置为true,并且在路由器更改时,我检查标志是否为true,然后不进行任何API调用.但随后它会清空文章列表.

I also tried to use sessionStorage to store one flag that if API calls fired then flag set to true and on router change I check if flag is true then don't make any API calls. But then it blanks the list of articles.

我有一个包含路线的主要App组件,其中包含两个组件:(请参见下面给出的代码)

I have one main App component with routes, which contains two components : ( Please see below given code )

  1. ArticleHome
  2. 书签主页

我面临的问题是,当我第一次点击http://localhost:3001时,它会重定向到http://localhost:3001/articles页面,并正确呈现ArticleHome组件并获取文章列表.然后我单击书签"链接,它呈现http://localhost:3001/bookmarks路线和相关组件,并进行API调用以呈现书签列表.

the problem which I am facing is, when I first time hits http://localhost:3001, it redirects to http://localhost:3001/articles page and it renders ArticleHome component properly and fetches list of Articles. then I click on Bookmarks link and it renders http://localhost:3001/bookmarks route and related component and makes and API call to render bookmark list.

但是当我使用路由器http://localhost:3001/articles返回到文章"页面时,由于每次更改路线时都会重新渲染组件,因此它再次触发API调用以获取文章.

But when I go back to Articles page using router http://localhost:3001/articles it again fires API call to fetch articles due to component re-renders on each route change.

任何人都可以指导我如何在更换路由器和重新渲染组件时停止再次执行API调用?

Can anyone pleae guide that how can I stop executing API calls again on router change and on component re-render?

如果已经加载了数据,是否有更好的方法来处理同一组件的路由器更改上的API调用?

Is there any better way to handle API calls on router change for the same component, if data is already loaded?

class App extends React.Component<any, any> {

    constructor(props: any) {
        super(props);
    }

    render() {
        return (
            <Router>
                <React.Fragment>
                    <Switch>
                        <Route exact path="/" render={() => <Redirect to="/articles" />} />
                        <Route path="/articles" render={() => <ArticleHome type="articles" />} />
                        <Route path="/bookmarks" render={() => <BookmarkHome type="bookmarks" />} />
                        <Route path="*" component={NoMatch} />
                    </Switch>
                </React.Fragment>
            </Router>
        );
    }
}

export default App;

在ArticleHome组件中,我有一个API调用可获取文章列表,而在 BookmarkHome组件我还有另一个API调用,可获取书签列表.

In ArticleHome component I have one API call which fetches list of Articles and in BookmarkHome component I have another API call which fetches list of Bookmarks.

ArticleHome组件:(与BookmarkHome组件相同的功能)

ArticleHome component: ( Same function for BookmarkHome component )

import React, { useReducer, useEffect, useState } from "react";

const ArticleHome = (props: any) => {

    const [state, setState] = useState({
        articles: [],
        reRender: true
    });

    const [newState, dispatch] = useReducer(articleReducer, state);

    useEffect(() => {


        // componentWillUnmount
        return () => {

            console.log('unmounting 1...');
            setState({
                ...state,
                reRender: false
            });
        }

    },[state.reRender]); // componentDidUpdate

    const fetchAllrecords = () => {
        fetch(url)
        .then((data: any) => {

            dispatch({ type: 'GET_ALL_RECORDS', data: data.docs })

            return data.docs;
        })
    }

return (
    <ul>
        <li>Render article list here</li>
    </ul>
)
}


// Reducer function
// ========================

function articleReducer(state: any, action: any) {
    switch (action.type) {
        case "GET_ALL_RECORDS":
            return {
                ...state,
                articles: action.data,
                reRender: false
            }
        }
        default:
            return state;
    }
}

但是当我使用路由器切换到上述任何组件时,它会再次执行API调用.

But when I switch to any of the above mentioned components using router it again executes API call.

我已经在useEffect挂钩中传递了[state.reRender],以告诉响应仅在添加任何新项目或更新数据时重新渲染组件.

I have passed [state.reRender] in useEffect hook to tell react that re-render component only when any new items added or data updates.

articleReducer功能中,我正在设置reRender: false.

In articleReducer function I am setting reRender: false.

如果您需要进一步的信息,请告诉我.

Please let me know if you need further information on this.

谢谢, 吉涅什·拉瓦尔(Jignesh Raval)

Thanks, Jignesh Raval

推荐答案

如果您是我,我会从我的api中获取路由组件之外的内容,然后将其传递到路由中.这样,您就不必担心路由更改以及操纵路由器默认行为所涉及的任何编程.您可以通过以下两种方法之一来执行此操作.

If I were you I would fetch from my api outside of the route components and just pass it down to the route. Then you don't have to worry about the route change and any programming that would be involved in manipulating the default behavior of the router. You can do this one of two ways.

第一 在组件树中将您的api调用调高些.因此,如果您在应用程序组件中进行api调用,然后将其传递给Route,则无需担心路由的呈现.您的逻辑将不合逻辑.

First Do your api call higher in the component tree. So if you would do your api call in the app component then pass it down to the Route you wouldn't have to worry about the rendering of the route. Your logic would be outside of it.

第二 如果您不希望使用杂乱的应用程序组件,则可以创建一个上下文组件,然后在其中进行逻辑处理.然后,只需将您的组件包装在您创建的上下文组件中即可.像这样:

Second If you don't want a messy app component you could create a context component and do your logic in there. Then just wrap your components in your context component that you created. Like so:

这是一个代码框沙盒

您的应用程序组件

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Link, Switch } from "react-router-dom";

import First from "./First";
import Second from "./Second";
import Context from "./Context";
import "./styles.css";

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h1>Router Rerendering Fix</h1>
        <ul>
          <li>
            <Link to="/">First Route</Link>
          </li>
          <li>
            <Link to="/second">Second Route</Link>
          </li>
        </ul>
        <Switch>
          <Context>
            <Route exact path="/" component={First} />
            <Route path="/second" component={Second} />
          </Context>
        </Switch>
      </div>
    </BrowserRouter>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

您的文章部分

import React, { useContext } from "react";
import {ApiContext} from "./Context";

const First = () => {
  const context = useContext(ApiContext);
  return (
    <div>
      <div>First Route</div>
      <ul>
        {context.map((article, index) => (
          <li key={index}>{article}</li>
        ))}
      </ul>
    </div>
  );
};

export default First;

您的上下文组件

import React, {useState, useEffect} from 'react';

export const ApiContext = React.createContext();

const Context = props => {
  const [articles, setArticles] = useState([]);

  useEffect(() => {
    console.log('rendered');
    setArticles(['Article One', 'Article Two', '...ect'])
  }, []);

  return (
    <ApiContext.Provider value={articles}>
      {props.children}
    </ApiContext.Provider>
  )
}

export default Context;

这篇关于React:如何停止重新渲染组件或更改同一路由的路由器上的API调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆