Skip to content

Commit

Permalink
refactor(usecontrolledstate): refactor usecontrolledstate (#1369)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhaoting zhou authored Oct 20, 2021
1 parent ba32640 commit 06750d0
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 45 deletions.
4 changes: 2 additions & 2 deletions src/utils/demos/useControlled/useControl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
### 使用了 useControll 的组件 Counter

```javascript
export const Counter = ({ value, onChange, defaultValue }) => {
const [state, setState] = useControlledState(value, onChange, defaultValue);
export const Counter = ({ value, onChange, defaultValue }: IProps) => {
const [state, setState] = useControlledState(value, defaultValue, onChange);
return (
<>
<button type="button" onClick={() => setState(state - 1)}>
Expand Down
4 changes: 2 additions & 2 deletions src/utils/demos/useControlled/useControl.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import useControlledState from '../../hooks/useControlled';
import useControlledState from '../../hooks/useControlledState';
import Docs from './useControl.mdx';

interface IProps {
Expand All @@ -9,7 +9,7 @@ interface IProps {
}

export const Counter = ({ value, onChange, defaultValue }: IProps) => {
const [state, setState] = useControlledState(value, onChange, defaultValue);
const [state, setState] = useControlledState(value, defaultValue, onChange);
return (
<>
<button type="button" onClick={() => setState(state - 1)}>
Expand Down
28 changes: 0 additions & 28 deletions src/utils/hooks/useControlled.ts

This file was deleted.

38 changes: 25 additions & 13 deletions src/utils/hooks/useControlledState.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import { useState, useEffect, useRef } from 'react';
import { useState, useEffect, useRef, Dispatch, SetStateAction, useDebugValue } from 'react';
import { isUndefined } from 'lodash';

function format<T>([innerState, outterState]: [T, T]) {
const isControlled = isUndefined(outterState) ? 'uncontrolled' : 'controlled';
const value = isUndefined(outterState) ? innerState : outterState;
return `State is ${isControlled} | Value is ${value}`;
}

const useControlledState = <T>(
controlledState: T | (() => T) | undefined,
empty: T
): [T, (_state: T | (() => T), force?: boolean) => void] => {
const [_controlledState, setControlledState] = useState<T>(controlledState === undefined ? empty : controlledState);

const setState = useRef((_state: T | (() => T), force = false) => {
if (controlledState === undefined || force) {
setControlledState(_state);
outterState?: T | (() => T),
defaultOutterState?: T,
callback?: (state: T | (() => T)) => void
): [T | undefined, (state: T | Dispatch<SetStateAction<T>>, force?: boolean) => void] => {
const [innerState, setInnerState] = useState<T>(isUndefined(outterState) ? defaultOutterState : outterState);

const setState = useRef((state: T | (() => T), force = false) => {
if (isUndefined(outterState) || force) {
setInnerState(state);
}

callback?.(state);
}).current;

useDebugValue([innerState, outterState], format);

useEffect(() => {
if (controlledState !== undefined) {
setControlledState(controlledState);
if (!isUndefined(outterState)) {
setInnerState(outterState);
}
}, [controlledState]);
}, [outterState]);

return [_controlledState, setState];
return [innerState, setState];
};

export default useControlledState;

1 comment on commit 06750d0

@vercel
Copy link

@vercel vercel bot commented on 06750d0 Oct 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.