Skip to content

Commit

Permalink
feat: improve useToggle interface
Browse files Browse the repository at this point in the history
BREAKING CHANGE: useToggle interface changed
  • Loading branch information
streamich authored May 9, 2019
2 parents 351aebd + 3bd1cbc commit 81b1cac
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 18 deletions.
3 changes: 1 addition & 2 deletions docs/useToggle.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ React state hook that tracks value of a boolean.

`useBoolean` is an alias for `useToggle`.


## Usage

```jsx
Expand All @@ -16,7 +15,7 @@ const Demo = () => {
return (
<div>
<div>{on ? 'ON' : 'OFF'}</div>
<button onClick={() => toggle()}>Toggle</button>
<button onClick={toggle}>Toggle</button>
<button onClick={() => toggle(true)}>set ON</button>
<button onClick={() => toggle(false)}>set OFF</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/__stories__/useToggle.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Demo = () => {
return (
<div>
<div>{on ? 'ON' : 'OFF'}</div>
<button onClick={() => toggle()}>Toggle</button>
<button onClick={toggle}>Toggle</button>
<button onClick={() => toggle(true)}>set ON</button>
<button onClick={() => toggle(false)}>set OFF</button>
</div>
Expand Down
49 changes: 49 additions & 0 deletions src/__tests__/useToggle.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { act, cleanup, renderHook } from 'react-hooks-testing-library';
import useToggle from '../useToggle';

afterEach(cleanup);

describe('useToggle', () => {
it('should be defined', () => {
expect(useToggle).toBeDefined();
});

const hook = renderHook(props => useToggle(props), { initialProps: false });

it('should return initial state on initial render', () => {
expect(hook.result.current[0]).toBe(false);
});

it('should update state with correct value', () => {
hook.rerender(true);
expect(hook.result.current[0]).toBe(true);

act(() => {
hook.result.current[1](false);
});

expect(hook.result.current[0]).toBe(false);
});

// it('should toggle state without a value parameter', () => {
// act(() => {
// hook.result.current[1]();
// });

// expect(hook.result.current[0]).toBe(true);
// });

// it('should ignore non-boolean parameters', () => {
// act(() => {
// hook.result.current[1]('string');
// });

// expect(hook.result.current[0]).toBe(true);

// act(() => {
// hook.result.current[1]({});
// });

// expect(hook.result.current[0]).toBe(false);
// });
});
22 changes: 7 additions & 15 deletions src/useToggle.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import { useCallback, useState } from 'react';

export type UseToggle = (
state: boolean
) => [
boolean, // state
(nextValue?: boolean) => void // toggle
];

const useToggle: UseToggle = state => {
const [value, setValue] = useState<boolean>(state);
const useToggle = (initialValue: boolean): [boolean, (nextValue?: any) => void] => {
const [value, setValue] = useState<boolean>(initialValue);

const toggle = useCallback(
(nextValue?: boolean) => {
if (typeof nextValue !== 'undefined') {
setValue(!!nextValue);
return;
(nextValue?: any) => {
if (typeof nextValue === 'boolean') {
setValue(nextValue);
} else {
setValue(currentValue => !currentValue);
}

setValue(newValue => !newValue);
},
[setValue]
);
Expand Down

0 comments on commit 81b1cac

Please sign in to comment.