Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve useValue type inference #1617

Merged
merged 4 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/todo/src/components/TodoContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type ProviderProps = {
children: React.ReactNode;
};
export function TodoProvider({ children }: ProviderProps) {
const [todos, setTodos] = useValue<Todo[]>('todos', {
const [todos, setTodos] = useValue('todos', {
defaultValue: React.useMemo(
() => [
{
Expand Down
4 changes: 2 additions & 2 deletions examples/todo/src/components/TodoList/TodoItem.fixture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { useValue } from 'react-cosmos/client';
import { TodoItem } from './TodoItem.js';

export default () => {
const [label, setLabel] = useValue<string>('label', {
const [label, setLabel] = useValue('label', {
defaultValue: 'Eat the homework',
});

const [done, setDone] = useValue<boolean>('done', {
const [done, setDone] = useValue('done', {
defaultValue: false,
});

Expand Down
2 changes: 1 addition & 1 deletion examples/vite/src/CounterButton.fixture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { useValue } from 'react-cosmos/client';

export default () => {
const [count, setCount] = useValue<number>('count', { defaultValue: 0 });
const [count, setCount] = useValue('count', { defaultValue: 0 });
return (
<CounterButton
suffix="times"
Expand Down
2 changes: 1 addition & 1 deletion examples/webpack/src/CounterButton.fixture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { useValue } from 'react-cosmos/client';

export default () => {
const [count, setCount] = useValue<number>('count', { defaultValue: 0 });
const [count, setCount] = useValue('count', { defaultValue: 0 });
return (
<CounterButton
suffix="times"
Expand Down
2 changes: 0 additions & 2 deletions packages/react-cosmos-core/src/fixtureState/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ export type ObjectData = Record<string, unknown>;

export type ArrayData = unknown[];

export type FixtureStateData = PrimitiveData | ObjectData | ArrayData;

export type FixtureStatePrimitiveValue = {
type: 'primitive';
data: PrimitiveData;
Expand Down
8 changes: 3 additions & 5 deletions packages/react-cosmos-renderer/src/fixture/useValue/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { FixtureStateData } from 'react-cosmos-core';
import { SetValue } from './shared.js';
import { useCreateFixtureState } from './useCreateFixtureState.js';
import { useCurrentValue } from './useCurrentValue.js';
import { useSetValue } from './useSetValue.js';

type Opts<T extends FixtureStateData> = {
type Opts<T> = {
defaultValue: T;
};

export function useValue<T extends FixtureStateData>(
export function useValue<T>(
inputName: string,
{ defaultValue }: Opts<T>
): [T, SetValue<T>] {
): [T, React.Dispatch<React.SetStateAction<T>>] {
useCreateFixtureState(inputName, defaultValue);
const currentValue = useCurrentValue(inputName, defaultValue);
const setValue = useSetValue(inputName, defaultValue);
Expand Down
6 changes: 0 additions & 6 deletions packages/react-cosmos-renderer/src/fixture/useValue/shared.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { isEqual } from 'lodash-es';
import React from 'react';
import {
ControlsFixtureState,
FixtureStateData,
FixtureStateValue,
createValue,
extendWithValue,
Expand All @@ -11,7 +10,7 @@ import { useFixtureState } from '../useFixtureState.js';

export function useCreateFixtureState(
inputName: string,
defaultValue: FixtureStateData
defaultValue: unknown
) {
const [, setFixtureState] = useFixtureState<ControlsFixtureState>('controls');
React.useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import {
ControlsFixtureState,
FixtureStateData,
extendWithValue,
} from 'react-cosmos-core';
import { ControlsFixtureState, extendWithValue } from 'react-cosmos-core';
import { useFixtureState } from '../useFixtureState.js';

export function useCurrentValue<T extends FixtureStateData>(
inputName: string,
defaultValue: T
): T {
export function useCurrentValue<T>(inputName: string, defaultValue: T): T {
const [fixtureState] = useFixtureState<ControlsFixtureState>('controls');
const controlFs = fixtureState && fixtureState[inputName];
return controlFs && controlFs.type === 'standard'
? // Types of fixture state values cannot be guaranteed at read time, which
? // Types of fixture state values cannot be guaranteed at run time, which
// means that tampering with the fixture state can cause runtime errors
(extendWithValue(defaultValue, controlFs.currentValue) as T)
: defaultValue;
Expand Down
34 changes: 15 additions & 19 deletions packages/react-cosmos-renderer/src/fixture/useValue/useSetValue.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,37 @@
import React from 'react';
import {
ControlsFixtureState,
FixtureStateData,
createValue,
extendWithValue,
} from 'react-cosmos-core';
import { useFixtureState } from '../useFixtureState.js';
import { SetValue } from './shared.js';

export function useSetValue<T extends FixtureStateData>(
export function useSetValue<T>(
inputName: string,
defaultValue: T
): SetValue<T> {
): React.Dispatch<React.SetStateAction<T>> {
const [, setFixtureState] = useFixtureState<ControlsFixtureState>('controls');
return React.useCallback(
stateChange => {
setFixtureState(prevFs => {
const currentValue: FixtureStateData =
typeof stateChange === 'function'
? stateChange(
// Types of fixture state values cannot be guaranteed at read
// time, which means that tampering with the fixture state can
// cause runtime errors
getCurrentValueFromFixtureState(
prevFs,
inputName,
defaultValue
) as T
)
: stateChange;
// Types of fixture state values cannot be guaranteed at run
// time, which means that tampering with the fixture state can
// cause runtime errors
function getNewState() {
if (typeof stateChange !== 'function') return stateChange;

const stateUpdater = stateChange as (prevState: unknown) => unknown;
return stateUpdater(
getCurrentValueFromFixtureState(prevFs, inputName, defaultValue)
);
}

return {
...prevFs,
[inputName]: {
type: 'standard',
defaultValue: createValue(defaultValue),
currentValue: createValue(currentValue),
currentValue: createValue(getNewState()),
},
};
});
Expand All @@ -47,7 +43,7 @@ export function useSetValue<T extends FixtureStateData>(
function getCurrentValueFromFixtureState(
fixtureState: ControlsFixtureState | undefined,
inputName: string,
defaultValue: FixtureStateData
defaultValue: unknown
) {
const controlFs = fixtureState && fixtureState[inputName];
return controlFs && controlFs.type === 'standard'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ const Container = styled.div`
`;

export default () => {
const [nr1, setNr1] = useValue<number>('number1', { defaultValue: 0.93 });
const [nr2, setNr2] = useValue<number>('number2', { defaultValue: 1337 });
const [nr3, setNr3] = useValue<number>('number3', { defaultValue: 0 });
const [nr1, setNr1] = useValue('number1', { defaultValue: 0.93 });
const [nr2, setNr2] = useValue('number2', { defaultValue: 1337 });
const [nr3, setNr3] = useValue('number3', { defaultValue: 0 });
return (
<Container>
<NumberInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default {

function createFixture(fixtureId: null | FixtureId = null) {
return () => {
const [searchText, setSearchText] = useValue<string>('searchText', {
const [searchText, setSearchText] = useValue('searchText', {
defaultValue: '',
});
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default () => {
const [viewport, setViewport] = useValue('viewport', {
defaultValue: initialViewport,
});
const [scaled, setScaled] = useValue<boolean>('scaled', {
const [scaled, setScaled] = useValue('scaled', {
defaultValue: false,
});
const scaleFactor = getViewportScaleFactor(viewport, containerViewport);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default () => {
const [viewport, setViewport] = useValue('viewport', {
defaultValue: initialViewport,
});
const [scaled, setScaled] = useValue<boolean>('scaled', {
const [scaled, setScaled] = useValue('scaled', {
defaultValue: false,
});
return (
Expand Down
Loading