Skip to content

Commit

Permalink
Correct fromInput modifier usage
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Nov 22, 2023
1 parent 4f72f7c commit d2383c8
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,47 @@ describe('useDataValue', () => {
})
})

describe('value manipulation', () => {
it('should call fromInput and toInput', () => {
const fromInput = jest.fn((v) => v + 1)
const toInput = jest.fn((v) => v - 1)
const onChange = jest.fn()

const { result } = renderHook(() =>
useDataValue({
value: 1,
onChange,
fromInput,
toInput,
})
)

const { handleChange } = result.current

act(() => {
handleChange(2)
})

expect(fromInput).toHaveBeenCalledTimes(1)
expect(toInput).toHaveBeenCalledTimes(2)
expect(fromInput).toHaveBeenLastCalledWith(2)
expect(toInput).toHaveBeenLastCalledWith(3)

act(() => {
handleChange(4)
})

expect(fromInput).toHaveBeenCalledTimes(2)
expect(toInput).toHaveBeenCalledTimes(3)
expect(fromInput).toHaveBeenLastCalledWith(4)
expect(toInput).toHaveBeenLastCalledWith(5)

/**
* NB: "forceUpdate" is initiator that "toInput" is called more often.
*/
})
})

describe('updating internal value', () => {
it('should update the internal value, but not call any event handler', () => {
const onFocus = jest.fn()
Expand All @@ -132,7 +173,6 @@ describe('useDataValue', () => {
const { result } = renderHook(() =>
useDataValue({
value: 'foo',
emptyValue: '',
onFocus,
onBlur,
onChange,
Expand Down Expand Up @@ -164,6 +204,58 @@ describe('useDataValue', () => {
expect(onBlur).toHaveBeenCalledTimes(2)
})

it('should not call fromInput', () => {
const fromInput = jest.fn((v) => v)
const toInput = jest.fn((v) => v)
const onChange = jest.fn()

const { result } = renderHook(() =>
useDataValue({
value: 'foo',
onChange,
fromInput,
toInput,
})
)

const { updateValue, handleChange } = result.current

act(() => {
updateValue('')
})

expect(fromInput).toHaveBeenCalledTimes(0)

act(() => {
updateValue('bar')
})

expect(fromInput).toHaveBeenCalledTimes(0)
expect(onChange).toHaveBeenCalledTimes(0)

act(() => {
handleChange('')
})

expect(fromInput).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenCalledTimes(1)

act(() => {
updateValue('unchanged')
})

expect(fromInput).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenCalledTimes(1)

act(() => {
handleChange('unchanged')
})

expect(fromInput).toHaveBeenCalledTimes(2)
expect(toInput).toHaveBeenCalledTimes(5)
expect(onChange).toHaveBeenCalledTimes(1)
})

it('should update the internal value and run error validation', async () => {
const onFocus = jest.fn()
const onBlur = jest.fn()
Expand Down
14 changes: 6 additions & 8 deletions packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export default function useDataValue<
validateInitially,
validateUnchanged,
continuousValidation,
toInput = (value) => value,
fromInput = (value) => value,
toInput = (value: Value) => value,
fromInput = (value: Value) => value,
} = props
const [, forceUpdate] = useReducer(() => ({}), {})
const { startProcess } = useProcessManager()
Expand Down Expand Up @@ -373,9 +373,7 @@ export default function useDataValue<
const handleBlur = useCallback(() => setHasFocus(false), [setHasFocus])

const updateValue = useCallback(
(argFromInput) => {
const newValue = fromInput(argFromInput)

(newValue: Value) => {
if (newValue === valueRef.current) {
// Avoid triggering a change if the value was not actually changed. This may be caused by rendering components
// calling onChange even if the actual value did not change.
Expand All @@ -396,6 +394,7 @@ export default function useDataValue<
// When changing the value, hide errors to avoid annoying the user before they are finished filling in that value
hideError()
}

// Always validate the value immediately when it is changed
validateValue()

Expand All @@ -408,7 +407,6 @@ export default function useDataValue<
[
continuousValidation,
dataContextHandlePathChange,
fromInput,
hideError,
path,
showError,
Expand All @@ -417,7 +415,7 @@ export default function useDataValue<
)

const handleChange = useCallback(
(argFromInput) => {
(argFromInput: Value) => {
const newValue = fromInput(argFromInput)

if (newValue === valueRef.current) {
Expand All @@ -426,7 +424,7 @@ export default function useDataValue<
return
}

updateValue(argFromInput)
updateValue(newValue)

changedRef.current = true
onChange?.(newValue)
Expand Down

0 comments on commit d2383c8

Please sign in to comment.