0

I'm using Types in React for the first time and I'm not very familiar with it.

I'm trying to add numbers from a form in a child component to an array of numbers.

Therefor I have created a useState hook:

const [valuesList, setValuesList] = useState<number[]>([]);

Now I'm trying to pass the setValuesList hook to the child component:

<AddNum
        setValues={setValuesList}
      />

In the child component I'm defining an interface for the props:

interface AppProps {
  setValues: (value: number) => void;
}

However when I try to call the setValues hook:

const addNumber = (value: string): undefined => {
const num = parseInt(value);
props.setValues((prevList) => prevList.concat(num));
return undefined;

};

I'm getting this error in the parent component:

/Users/acandael/Tutorials/react/add-nums/src/components/AddNum.tsx
TypeScript error in /Users/acandael/Tutorials/react/add-nums/src/components/AddNum.tsx(21,21):
Argument of type '(prevList: any) => any' is not assignable to parameter of type 'number[]'.
  Type '(prevList: any) => any' is missing the following properties from type 'number[]': pop, push, concat, join, and 27 more.  TS2345

    19 |   const addNumber = (value: string): undefined => {
    20 |     const num = parseInt(value);
  > 21 |     props.setValues((prevList) => prevList.concat(num));
       |                     ^
    22 |     return undefined;
    23 |   };
    24 | 

Does anyone know how I can add numbers from a child component to an array of numbers in the parent component, and keep TypeScript happy?

Thanks for your help

3
  • What is num? Is that a number or an array of numbers? Commented Jul 15, 2020 at 14:32
  • @RameshReddy num is a number Commented Jul 15, 2020 at 14:39
  • Did you change the interface as in my updated answer? Commented Jul 15, 2020 at 15:12

1 Answer 1

1

You are trying to change the state value of an array of numbers to a number by calling props.setValue(num).

Also the type definition for setValues in interface AppProps is incorrect. TS will infer the type of the setter function setValuesList as React.Dispatch<SetStateAction<number[]>> which is incompatible with the type (value: number) => void.

The correct definition for the setValues function would be if you want to pass the function setValuesList as props.

interface AppProps {
   setValues: React.Dispatch<SetStateAction<number[]>>
 
   // setValues: (numArr: number[]) => void  ( this will work as well )
}

The solution for updating the state value of valuesList would be to either use functional update or to create another callback function that receives a number as argument and updates the state.

With functional update

setValues(prev => prev.concat(num))

With setValues as a different callback function

// with this solution you don't need to modify the interface AppProps

interface AppProps {
   setValues: (num: number) => void
}

const Foo: React.FC<AppProps> = ({ setValues }) => {
  
  // component logic
  
  return (
   <>
   </>
  )
}

// in parent component
const [valuesList, setValuesList] = useState<number[]>([])

const updateWithNewValue = useCallback((num: number) => {
   setValuesList(prev => prev.concat(num))
}, [])

// pass the updateWithNewValue as props

<Foo setValues={updateWithNewValue}/>

A similar example in codesandbox

Sign up to request clarification or add additional context in comments.

5 Comments

thanks @subashMahapatra, I tried to implement your sollution with callback function, but then I get this error message: Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
That could be the result of how you call the setValues function inside the component.
I'm calling the setValues function like this: const addNumber = (value: string): undefined => { const num = parseInt(value); props.setValues(num); return undefined; };
Here is a codesandbox with everything working. Try to edit the sandbox with a minimal example of the issue.
thanks @subashMahapatra, I found the issue. Should have called my addNumber function like this: onClick={() => addNumber(props.value)}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.