Code Monkey home page Code Monkey logo

react-hooks-async's People

Contributors

dai-shi avatar dependabot[bot] avatar helloanoop avatar liroo avatar serg-plusplus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-hooks-async's Issues

In TypeAhead Demo, I don't see how abort is being called when query changes

I'm worried that you are not aborting you previous request when the query string is changed. It seems that you are just creating another task. I only see the .abort() called when you explicitly cancel by pressing the button.

Am I mis-understanding? seems like you'd need some kind of timer running and then when the query string changes, you'd need to abort the request and create another one (rather than just creating another one).

useFetch: Infinite re-rendering only when NODE_ENV=production

I am experiencing an infinite re-rendering (leading to infinite re-fetch) with the useFetch hook, but only when building in production mode (NODE_ENV=production), not in development-build or running with webpack dev-server.

Honestly I have no clues on how to further debug the issue. The hook depends on a static string only:

export default ({ selection, setSelection }: Props) => {
  const { result: availableData, ...props } = useFetch<AvailableDataMap>(dataFilesUrl);
  const nodes = useSelector(selectNodes);

  if (props.error) return <Alert color="error">{`Error fetching data: ${props.error}`}</Alert>;
  if (props.pending) return <Spinner type="grow" />;

  if (!selection || selection.length === 0) {
    setSelection(Object.keys(availableData).map(nodeId => ({ nodeId, filename: availableData[nodeId][0] })));
  }
  /* ... */

How to prevent an initial run

Hi,

Really like what you have done here, but have a query if that is ok ?

I want to run an async axios delete when the user clicks a button on a row of data. When the page loads i dont want to run the delete as the user has not selected the row yet. On my button click i am setting state to update the row to delete and the async delete function is run and the row deleted. How can i prevent it from running on initial load?

I tried following the example using start function so on my button click set state and call start but the function is run before the state update has taken affect and so the row info is still missing.

Not sure if the above makes sense. Let me know if you need more info.

Thanks, Ed

Issue with tests and .start() since 3.2.0

Apologies i tried to create code sandbox to recreate, but apparently doesnt support jest.mock which my test is using.

So thought i would raise and see if you could think of anything obvious.

Two of my unit tests started failing after upgrading to 3.2.0, both relate to async actions that are invoked by calling the start() function on button click, both are supposed to start axios tasks which i have mocked. The text on the button should change when the action completes, and this is working fine in the code but the unit test is suddenly failing. I am using react testing library to wait on the button state change, but the task.result never seems to resolve

Any thoughts greatly welcome.

Here is a simple example of the code https://codesandbox.io/s/wizardly-hooks-425yz
as you can see the button state does change, unfortunately i cant reproduce the failing test due to codesandbox not supporting jest.mock but you can see the test code at least.

Thanks, Ed

Typescript errors

When running typescript app, errors are shown in response from useAsyncTaskFetch because of unknown[] types.
See: Codesandbox.
Is there issue with typings or am I doing something wrong?

Error without statusText via HTTP/2 protocol

Hi

I use useFetch hook via HTTP/2 protocol. I need to handle Error via statusCode or statusText. According to the spec:

HTTP/2 does not define a way to carry the version or reason phrase that is included in an

It means i don't have methods for getting statusCode or statusText.
It is good idea to add statusCode to the error. What do you think?

Thanks

dependency on axios cause break in at least 04_typeahead

Nice work! Learning a lot here. Seems that there is a breaking dependency on axios and node-fetch someplace causing at least the 04_typeahead app to error with "npm start". I also noticed the same error from a codepen app but don't remember where.

Relying on object identity might not be a best practice

At this point, useAsyncTaskTimeout and useAsyncTaskAxios do rely on object identities.

Because it's said that useMemo/useCallback can't be used as a semantic guarantee,
it might be better to explicitly receive inputs in the last argument.

Ref: https://reactjs.org/docs/hooks-reference.html#usememo

You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.

Project maintenance and future of data fetching

This is not an issue, but a topic for discussion. I noticed, that there is a message about the future of the repo.

Quote:

The approach this project takes is so-called useEffect chaining, which will not be a best practice in the future versions of React.

Is this a reference to Suspense, or it's a reference to some other way of fetching data I am not aware of?

Should we throw an error when fetch is aborted?

Do we really need to throw an error without stacktrace when a fetch request is aborted ?

We could check the Error name as:

try {
    result = await func(task.abortController, ...args);
} catch (e) {
   if (e.name !== 'AbortError') {
      err = e;
   }
}

in order to reduce the number of error in the console. Furthermore it's not an error, it's a wanted behavior that we want to abort the error with a signal.

What do you think?

Chaining async fetches

How can I chain fetch tasks together of the url of a second task depends on the result of the first one?

const task1 = useFetch(url1)
const task2 = useFetch(url2(task1.result.key))

How to handle FetchError?

He there,

Thank you for creating these hooks, they are really useful for me.

One thing I noticed is when a request returns 404, an additional message propagates to console:

Uncaught (in promise) FetchError: Not Found
    at createFetchError

Is there a way to efficiently handle FetchError and avoid error message propagation in console?

infinite re-rendering when calling useAsyncTaskFetch hook

I am calling useAsyncTaskFetch from one of my own hooks:

export const useApi = <TResponse>(
  url: string,
  options: UseApiOptions<TResponse> = { httpMethod: HTTPMethod.GET },
): UseApiResult<TResponse> => {
  // TODO: needed to add useMemo  with empty deps to stop
  // infinite re-rendering
  // eslint-disable-next-line
  const config = useMemo(() => createConfig(options), []);

  const asyncTask = useAsyncTaskFetch<TResponse>(url, config);
  useAsyncRun(asyncTask);

This is causing a re-render because the options object being a new object each time if I do not use useMemo or something.

Is this expected behaviour?

Return a promise from task.start()

What do you think if task.start() function would return a promise which could be fulfilled with task's results or rejected in case of error?

In some scenarios, it's more preferable rather than tracking task's pending/result values,
i.e. const { pending, error, result } = task;

handling abort in useAsyncTask start().then

Hi, thank you very much for this library, it has simplified and standardized how I fetch things. I'm running into a little confusion with the types returned by the start function in useAsyncTask. The types show it typed as start: (...args: Args) => Promise<Result | symbol>; If a symbol is returned does that mean the request was aborted? Here's a codesandbox which illustrates the problem: https://codesandbox.io/s/wild-browser-f9nuq?file=/src/App.tsx

The relevant code starts on line 35 -

onClick={() =>
          start(id).then((data) => {
            if (typeof data === "symbol") {
              return; // data is of type symbol, does this mean the request was aborted?
            }
            console.log(data); // data is of type Post
          })
        }

using asyncTask without useEffect

I just want to check I have not missed anything when you say there should be a better abstraction from #6.

There currently is no better abstraction, I see useEffect used in asyncTask?

I sort of struggle to see the usefulness of all these hook libraries if they cannot be used in event handlers.

I really want to check that I am not missing something about why these libraries exist when a major use case is not possible.

I have seen the start example but start does not take any arguments, what if the api call is made when say an autocomplete is selected?

useAsyncTaskFetch: pending is "true" from the start

Hi, noticed some weird behaviour when firing useAsyncTaskFetch by using the .start() method.

Pending status is set to true when fetch is not started, and also .started is not set to false after fetch is complete.

Here's demo:
https://codesandbox.io/s/react-hooks-async-demo-ebe5n
You can see loading state from the start, and button is disabled after fetch is done.

Also, maybe it's codesandbox related, but after installing "react-hooks-async" dependency, there was an error

Could not find dependency: 'core-js' relative to '/node_modules/react-hooks-async/dist/index.js'

so i had to add it manually.

ADDED 30.08.19
Found one more thing.
If you remove disabled attribute of the button in that codesanbox demo, and fire another fetch while previous is running (better do it in slow3g mode), the request is canceled and another one is started, that's ok, but the task has pending status false .
I looked into use-async-task.js and it looks like after firing next request,
forceUpdateRef.current(func); of the previous task object runs after forceUpdateRef.current(func); of the next task. So we get pending state of the finished task.
As a workaround i added this to the task object:

safeStart: () => {
      task.abort();
      setTimeout(() => {
        task.start();
      }, 0);

and exporting it as a start method

  return useMemo(
    () => ({
      start: task.safeStart,

and it worked ok, JFYI

Error compiling

I create a new project using latest create-react-app then install this lib.
I then paste in the useFetch demo code from the README.
When compiling I get the following error:

./node_modules/react-hooks-async/dist/use-async-task-fetch.js
Module not found: Can't resolve 'core-js/modules/es6.array.filter' in '/Users/mynamehere/Desktop/myprojectname/node_modules/react-hooks-async/dist'

It's strange because that module is definitely in that location inside node_modules. Any ideas? Thanks

useAsyncTaskFetch doesn't provide access the response body if server returns error

Hi there, thank you for the great library!

I've found that useAsyncTaskFetch doesn't allow to get access to the server response body if an error occurred.

Here it returns only statusText, but in some cases, it can be not enough.

In my particular case, the server responds with 500 error and the body:

{
  "errorId": "a70eb1e0-0d11-4d6c-8ace-d3043f7e5bfc",
  "errorCode": 10215,
  "errorMessage": "Campaign item with such name already exists",
  "params": "{}"
}

But hook's error contains only - FetchError: Server error.

Thanks again for the work you do!

3.1.0 breaks conditional running with useAsyncRun

The documentation for useAsyncRun says

This can be a falsy value and in that case it won't run any tasks. Hence, it's possible to control the timing by:
useAsyncRun(ready && task);

But v.3.1.0 removes the falsy check from useAsyncRun (line 4), so I get an error: TypeError: Cannot read property 'start' of null. Is there a different way to do this now?

How to combine this with a custom object that uses axios?

I have the following code:

import axios, { CancelToken } from 'axios';

export default class Client {
    public async getDevices(abortController?: AbortController): Promise<Device[]> {        
        var result = await axios.get<ODataResponse<Device>>('/odata/devices/', { cancelToken: toCancelToken(abortController) });
        return result.data.value;
    }

    public async getDevice(id: number, abortController?: AbortController): Promise<Device> {
        var result = await axios.get<ODataResponse<Device>>('/odata/devices/' + id + '?$expand=tags($select=tag,value),sensorDistances($select=rssi;$expand=sensor($select=name))', { cancelToken: toCancelToken(abortController) });
        return result.data.value[0];
    }

    public async addDevice(device: Device, abortController?: AbortController): Promise<void> {
        await axios.post<Device>('/odata/devices', device, { cancelToken: toCancelToken(abortController) });
    }

    public async editDevice(device: Device, abortController?: AbortController): Promise<void> {
        await axios.patch('/odata/devices/' + device.id, device, { cancelToken: toCancelToken(abortController) });
    }
}

const toCancelToken = (abortController?: AbortController) => {
    if (abortController === null || abortController === undefined)
        return undefined;
    const source = axios.CancelToken.source();
    abortController.signal.addEventListener('abort', () => {
        source.cancel('canceled');
    });
    return source.token;
};

class ODataResponse<T> {
    public value: T[];
}

export class Device {
    public id: number;
    public macAddress: string;
    public ipAddress: string;
    public name: string;
}

How would i combine it with react-hooks-async?

Unhandled promise rejection error

I'm not sure how errors are supposed to be handled. I have the following function that returns a promise:

  getFacebookToken(): Promise<string> {
    return LoginManager.logInWithPermissions(['public_profile'])
      .then((response) => {
        if (response.isCancelled) {
          // This error is not handled.
          throw Error('Request canceled');
        } else {
          return AccessToken.getCurrentAccessToken();
        }
      })
      .then((response) => response.accessToken)
  }

When I use the above with useAsyncTask and if the promise throws an error, then this is not handled and, also, the task.error is always null.

Thank you in advance.

PS. I'm using this in React Native, not ReactJS.

importing from src

Hi,

Apologies as i am sure this a simple question but ...

When i import from src e.g.

import useAsyncTaskAxios from 'react-hooks-async/src/use-async-task-axios'

this works fine in my code but not in my tests

i get SyntaxError: Unexpected identifier

guessing its because the ES6 modules not compiling but not sure how to modify my jest config to sort it out. If i import from dist then the type information is not available?

jest.config.js

module.exports = {
    "roots": [
      "<rootDir>/src"
    ],
    "transform": {
      "^.+\\.tsx?$": "ts-jest"
    },
    "moduleDirectories": ["node_modules", "src"],
    "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ],
    "reporters": [ "default", "jest-junit" ]
  }

Any thoughts welcome thanks, Ed

Should include babel runtime with corejs as a regular dependency?

If you install this library, it may give errors such as this

Module not found: Can't resolve 'core-js/modules/es.array.concat' in '/home/cdiesh/src/jbrowse-components/node_modules/react-hooks-async/dist'   

I believe this is due to not including @babel/runtime-corejs2 as a regular dependency (or maybe @babel/runtime and core-js: 3 as dependencies? not exactly sure)

what is the purpose of the started flag

I was having a quick play around in this codesandbox.

I was following the examples which follow this pattern:

  if (!started) {
    return (
      <div>
        <button onClick={() => start()}>GET</button>
      </div>
    );
  }

  // code will never get here because started will be false by the time result has resolved

  if (error) return <Err error={error} />;
  if (pending) return <Loading abort={abort} />;

  if (!result) {
    return <div>No Beers today!</div>;
  }

  // display results

The problem is that in my example anyway.

By the time I have a result, started will be false.

I have to change the first if statement to this:

if (!started && !result) {

I wonder if rather than individual error, loading, pending states, there should actually be a state machine where you are only ever in one state rather than individual flags.

Or am I misunderstanding how started workds.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.