Home > OS >  Passing down a Typed useState Hook to a child component reading as undefined even when defaultState
Passing down a Typed useState Hook to a child component reading as undefined even when defaultState

Time:03-18

I have the following piece of code which is a snippet of the entire thing. Basically I am trying to have a form, with the option of creating multiple entries of the same form on a button click. The aim is to store the data in an array of objects where each object represents one form.

Parent Component

export interface IExperience {
    position: string,
    location: string, 
    startDate: string,
    endDate: string,
    description: string
}

const Experience = () => {
    let [preview,setPreview] = useState(false)
    let [data,setData] = useState<IExperience[]>([{position: '', location: '', startDate: '', endDate: '', description: ''}]) // Default state is not undefined
    let [button,setButton] = useState('Edit')

    return (
        <div className={styles.visitorContainer}>
            <Nav />
            {preview ? <Message setPreview={setPreview} data={data} setData={setData} /> : <Preview setPreview={setPreview} data={data} setData={setData} button={button} setButton={setButton}/>}
            <Foot />
        </div>
    )
}
 
export default Experience

Ignore the preview part as it is redundant for the problem I am facing.

Child Component

import React from 'react'
import { ReactNode, useState } from 'react'
import { IExperience } from '.'
import { Preview } from './preview'

export const Message = ( { setPreview }: any, { data,setData }: any ) => {
    let [count,setCount] = useState(0)
    let formRows: ReactNode = []

    const formHandler = (i:number) => {
        console.log(data) //Console log here also shows data is undefined

        return formRows = [
             (<div key={`innerDiv${i}`}>
                <div><h2>Entry {i 1}</h2></div>
                <div>
                    <label>Position</label>
                    <input type="text" placeholder='Engineer' onChange={(e) => setData({...data,position: e.target.value})} value={data.position} /> //Error is here (data is undefined)
                </div>
            </div>)
         ]
    }

    const updateHandler = () => {
        setCount(prev => prev 1)
    }

    return (
        <div>
            <div>
                <div>
                </div>
                <form onSubmit={(e) => sendData(e)}>
                    {[...Array(count 1)].map((d,i) => (<div key={`outerDiv${i}`} >{formHandler(i)}</div>))}
                    <div>
                        <input type="button" value=' ' onClick={() => updateHandler()} />
                    </div>
        
                </form>
            </div>
        </div>
    )
}

Again I am leaving out redundant stuff so that it stays focused on the problem.

I have book looking into this for the past couple of days and I couldn't find a solution online so I resorting to posting my own question.

Hope this the code is clear :)

CodePudding user response:

React components take only one single props object. The Message component in your code snippet is taking two arguements.

export const Message = (
  { setPreview }: any,  // arg 1
  { data, setData }: any // arg 2 undefined!
) => {

You should destructure all props from the first argument, the props object. Please double-check the types as I'm not extremely familiar with Typescript.

interface I_Message {
  setPreview: React.Dispatch<SetStateAction<boolean>>,
  data: IExperience[],
  setData: React.Dispatch<SetStateAction<IExperience>>
}

export const Message = ({ setPreview, data, setData }: I_Message) => {
  ...
  • Related