Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/inshadowin/use-create-signal

This hook is useState 2.0. returns getter-function instead of value, setter returns updated value. Handles any combinations of updates via useEffect, etc.
https://github.com/inshadowin/use-create-signal

better-use-state react-hooks react-use-state-hook solid-like-react-use-state

Last synced: 18 days ago
JSON representation

This hook is useState 2.0. returns getter-function instead of value, setter returns updated value. Handles any combinations of updates via useEffect, etc.

Awesome Lists containing this project

README

        

# use-create-signal

Implements createSignal from Solid-JS for React-JS

Lightweight package that fixes most useState problems:

- value is locked in scope
- setState doens't return value
- parallel updated only possible with predicates

## How to use

Just like you use useState

But value is a getter function

```tsx
type DefaultValueType = T | (() => T);

type UseCreateSignalType = (
defaultValue?: DefaultValueType
) => [() => T, (setter: SetStateAction) => T, T];
```

```jsx
const Component = () => {
const [getter, setter] = useCreateSignal('');

return setter(e.target.value)} />;
};
```

Or if you also need value, it's gonna be here

```jsx
const Component = () => {
const [getter, setter, value] = useCreateSignal('');

return setter(e.target.value)} />;
};
```

## Advantages

- `useCallback` / `useEffect` and others don't require to put value in deps
- consecutive `useEffect` have updated values
- parallel `useEffect` have actual updated values
- multiple child components will have actual updated values

## Downsides

- memo-components: getter is always the same function. so if you pass getter-function directly - also pass it's result

## Examples

```jsx
const Component = () => {
const [getter, setter] = useCreateSignal(() => 1); // or just useCreateSignal(1). it's the same as useState

const handleIncrement = useCallback(() => {
const newValue = setter(getter() + 1);
console.log('no deps required. newValue: ', newValue);
}, []);

const handleWowIncrement = useCallback(() => {
const newValue = setter(old => old + 1);
console.log('WOW. it returned value from predicate. Much wow', newValue);
}, []);

// these effects have values updated in between
useEffect(() => {
const value = getter();
console.log(setter(value + 1)); // return 2
}, []);
useEffect(() => {
const value = getter();
console.log(setter(value + 1)); // return 3
}, []);
useEffect(() => {
const value = getter();
// parallel effects didn't get updated values
// this does
if (value > 2) return;

console.log(setter(value + 1)); // won't execute
}, []);

return

I was clicked {getter()} times
;
};
```

```jsx
const InputWithValidation = ({ value, hasError, onValidation }) => {
useEffect(() => {
const isNotValid = value > 100;

onValidation(isNotValid);
}, [value]);

return 'Something';
};

const MultipleInputs = ({ onErrors }) => {
const [getFormErrors, setFormErrors] = useCreateSignal({});
const formErrors = getFormErrors();

const handleOnErrors = newErrors => {
setFormErrors(newErrors);
onErrors?.(newErrors);
};

return (



handleOnErrors({ ...getFormErrors(), first: isValid })
}
// this would fail, as only last input would be validated
// onValidation={isValid => handleOnErrors({ ...formErrors, first: isValid })}
/>

handleOnErrors({ ...getFormErrors(), second: isValid })
}
/>

handleOnErrors({ ...getFormErrors(), third: isValid })
}
/>

handleOnErrors({ ...getFormErrors(), fourth: isValid })
}
/>

handleOnErrors({ ...getFormErrors(), fifth: isValid })
}
/>

);
};
```