How to Access History Object Outside of a React Component

后端 未结 3 1183
南方客
南方客 2020-12-15 03:34

First of all, I am pretty familiar with the withRouter HoC, however, in this case, it doesn\'t help because I do not want to access the history object in a comp

3条回答
  •  被撕碎了的回忆
    2020-12-15 04:26

    I just encountered this same issue, and following is the solution I used to solve this problem.

    I ended up creating a factory function which returns an object that has all my services functions. In order to call this factory function, an object with the following shape must be provided.

    interface History {
        push: (location: string) => void;
    }
    
    

    Here is a distilled version of my factory function.

    const services = {};
    
    function servicesFactory(history: History) {
        const countries = countriesFactory(history);
        const local = {
            ...countries,
        };
        Object.keys(local).forEach(key => {
            services[key] = local[key];
        });
    
    }
    

    Now the file where this function is defined exports 2 things.

    1)This factory function

    2)the services object.

    This is what the countries service looks like.

    
    function countriesFactory(h: History): CountriesService {
        const countries: CountriesService = {
            getCountries() {
                return request({
                    method: "get",
                    endpoint: "/api/countries",
                }, h)
            }
        }
        return countries;
    }
    

    And finally here is what my request function looks like.

    function request({ method, endpoint, body }: Request, history: History): Promise> {
        const headers = {
            "token": localStorage.getItem("someToken"),
        };
        const result: Response = {
            data: null,
            error: null,
        };
        return axios({
            url: endpoint,
            method,
            data: body,
            headers,
        }).then(res => {
            result.data = res.data;
            return result;
        }).catch(e => {
            if (e.response.status === 401) {
                localStorage.clear();
                history.push("/login");
                return result;
            } else {
                result.error = e.response.data;
                return result;
            }
        });
    }
    

    As you can see the request function exepcts to have the history object passed to it which it will get from the service, and the service will get it from the services factory.

    Now the cool part is that I only ever have to call this factory function and pass the history object to it once in the entire app. After that I can simply import the services object and use any method on it without having to worry about passing the history object to it.

    Here is the code of where I call the services factory function.

    const App = (props: RouteComponentProps) => {
      servicesFactory(props.history);
      return (
        // my app and routes
      );
    }
    

    Hope someone else who finds this question will find this useful.

提交回复
热议问题