In my React Typescript project I've decided to move a logic of rendering StoreItems out of my main function (Store) to a seperate function ListItems, so it won't rerender too often. I wanted Store function to pass data from storeItems (../items.json) to ListItems, because later I'm going to implement some fetch data logic.
Store.tsx
import storeItems from "../data/items.json"
import { StoreItem } from "../components/StoreItem"
import { useLang } from "../context/LangContext"
import { IStoreItem } from "../common/types"
const ListItems = (items: IStoreItem[]) => {
return <>
{
items.map(item => (
<StoreItem key={item.id} {...item} />
))
}
</>
}
export default function Store() {
const { currentLangText } = useLang()
return <>
<h1>{ currentLangText.store_page.title }</h1>
<div className="store">
<ListItems items={storeItems} />
</div>
</>
}
And Typescript shows me this error:
I've tried to change the passing type like this: Store.tsx
// ...
interface StoreItemsProps {
items: IStoreItem[]
}
const ListItems = (items: StoreItemsProps) => {
return <>
{
items.items.map(item => (
<StoreItem key={item.id} {...item} />
))
}
</>
}
// ...
And it worked. But it requires to change items.map(...) to items.items.map(...) because there is no map() function in just items. Probably, it expects me to destruct the object I pass, but what if these objects are very complex, and ListItem don't really need to know what's inside of them, there is an another component to handle their content.
I guess, there is more simple and cleaner way to define function component property. Even if this logic moving is not the best practice, I need to know how do I handle these array passing moments.
In react, each functional component (essentially a function) takes only one props argument, so you can either use the "props" argument as:
const ListItems = (props) => {
const items: StoreItemsProps = props.items;
return <>
{
items.items.map(item => (
<StoreItem key={item.id} {...item} />
))
}
</>
}
or you can destruct the props this way:
const ListItems = ({items: StoreItempsProps}) => {
return <>
{
items.items.map(item => (
<StoreItem key={item.id} {...item} />
))
}
</>
}
or use the typescript way with React.FC template, where you can define the type of props fields: const ListItems: React.FC<{items: StoreItempsProps}> = ({items}) => {
return <>
{
items.items.map(item => (
<StoreItem key={item.id} {...item} />
))
}
</>
}
I think your confusion here comes from the fact that you are looking to define the type of the 'props' argument, which is not the react way, as the 'props' is always an object literal (an object consists of keys and their respective values). you can make each property of props as simple or as complicated as you like, but the 'props' itself will always be keys/values.