mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
Merge pull request #902 from ayush987goyal/pr/use-error
feat: add useError hook
This commit is contained in:
commit
51d53b76c7
@ -97,6 +97,7 @@
|
||||
- [`useCookie`](./docs/useCookie.md) — provides way to read, update and delete a cookie. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usecookie--demo)
|
||||
- [`useCopyToClipboard`](./docs/useCopyToClipboard.md) — copies text to clipboard.
|
||||
- [`useDebounce`](./docs/useDebounce.md) — debounces a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usedebounce--demo)
|
||||
- [`useError`](./docs/useError.md) — error dispatcher. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-useerror--demo)
|
||||
- [`useFavicon`](./docs/useFavicon.md) — sets favicon of the page.
|
||||
- [`useLocalStorage`](./docs/useLocalStorage.md) — manages a value in `localStorage`.
|
||||
- [`useLockBodyScroll`](./docs/useLockBodyScroll.md) — lock scrolling of the body element.
|
||||
|
||||
34
docs/useError.md
Normal file
34
docs/useError.md
Normal file
@ -0,0 +1,34 @@
|
||||
# `useError`
|
||||
|
||||
React side-effect hook that returns an error dispatcher.
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import { useError } from 'react-use';
|
||||
|
||||
const Demo = () => {
|
||||
const dispatchError = useError();
|
||||
|
||||
const clickHandler = () => {
|
||||
dispatchError(new Error('Some error!'));
|
||||
};
|
||||
|
||||
return <button onClick={clickHandler}>Click me to throw</button>;
|
||||
};
|
||||
|
||||
// In parent app
|
||||
const App = () => (
|
||||
<ErrorBoundary>
|
||||
<Demo />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```js
|
||||
const dispatchError = useError();
|
||||
```
|
||||
|
||||
- `dispatchError` — Callback of type `(err: Error) => void`
|
||||
@ -21,6 +21,7 @@ export { default as useDropArea } from './useDropArea';
|
||||
export { default as useEffectOnce } from './useEffectOnce';
|
||||
export { default as useEnsuredForwardedRef, ensuredForwardRef } from './useEnsuredForwardedRef';
|
||||
export { default as useEvent } from './useEvent';
|
||||
export { default as useError } from './useError';
|
||||
export { default as useFavicon } from './useFavicon';
|
||||
export { default as useFullscreen } from './useFullscreen';
|
||||
export { default as useGeolocation } from './useGeolocation';
|
||||
|
||||
19
src/useError.ts
Normal file
19
src/useError.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
const useError = (): ((err: Error) => void) => {
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
const dispatchError = useCallback((err: Error) => {
|
||||
setError(err);
|
||||
}, []);
|
||||
|
||||
return dispatchError;
|
||||
};
|
||||
|
||||
export default useError;
|
||||
46
stories/useError.story.tsx
Normal file
46
stories/useError.story.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { useError } from '../src';
|
||||
import ShowDocs from './util/ShowDocs';
|
||||
|
||||
class ErrorBoundary extends React.Component<{}, { hasError: boolean }> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error) {
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Something went wrong.</h1>
|
||||
<button onClick={() => this.setState({ hasError: false })}>Retry</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
const Demo = () => {
|
||||
const dispatchError = useError();
|
||||
|
||||
const clickHandler = () => {
|
||||
dispatchError(new Error('Some error!'));
|
||||
};
|
||||
|
||||
return <button onClick={clickHandler}>Click me to throw</button>;
|
||||
};
|
||||
|
||||
storiesOf('Side effects|useError', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../docs/useLocalStorage.md')} />)
|
||||
.add('Demo', () => (
|
||||
<ErrorBoundary>
|
||||
<Demo />
|
||||
</ErrorBoundary>
|
||||
));
|
||||
26
tests/useError.test.ts
Normal file
26
tests/useError.test.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { useError } from '../src';
|
||||
|
||||
const setup = () => renderHook(() => useError());
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should throw an error on error dispatch', () => {
|
||||
const errorStr = 'some_error';
|
||||
|
||||
try {
|
||||
const { result } = setup();
|
||||
|
||||
act(() => {
|
||||
result.current(new Error(errorStr));
|
||||
});
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(errorStr);
|
||||
}
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user