Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using TypeScript To Create A React Stateless Functional Component That Accepts Array

So I want to create a react component in typescript, imagelist, that displays a list of images, links and numbers.

My json looks something like this

{   "_id": "59c8ead6411f1e56f498a71b",   "images": [
    {
      "post_url": "http://www.Facebook.com/974",
      "image_url": "http://placehold.it/32x32",
      "count": 887
    },
    {
      "post_url": "http://www.Facebook.com/711",
      "image_url": "http://placehold.it/32x32",
      "count": 749
    }   ] }

I have a dashboard component that looks like this

import * as React from 'react'; 
const fakeData = require('./fake_data.json'); 
import ImageList from './ImageList';

export default class Dashboard extends React.Component {   render() {
    return (
      <div>
        <ImageList data={fakeData.images} />
      </div>
    );   } }

I have tried to define my imagelist component as follows

import * as React from 'react';

interface ImageListValue {
  post_url: string;
  image_url: string;
  count: number;
}

interface ImageListProps {
  data: ImageListValue[];
}

const ImageList = ({ data }: ImageListProps) => {
  return data.map(item => {
    return (
      <div key={item.post_url}>
        <a href={item.post_url}>{item.post_url}</a>
        <img src={item.image_url} />
        <h1>item.count</h1>
      </div>
    );
  });
};

export default ImageList;

There linter shows no problems in the ImageList component, but in the Dashboard component I get the following message.

JSX element type 'Element[]' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'Element[]'.
[ts] JSX element class does not support attributes because it does not have a 'props' property.

I'm not sure what this error message means. My first thought was that I needed to use a SFC type definition as described [here][1] [1]: https://medium.com/@iktakahiro/react-stateless-functional-component-with-typescript-ce5043466011 .

I changed my code to this

const ImageList: React.SFC<ImageListProps> = ({data}) => {
  return data.map(item => {
    return (
      <div key={item.post_url}>
        <a href={item.post_url}>{item.post_url}</a>
        <img src={item.image_url} />
        <h1>item.count</h1>
      </div>
    );
  });
};

and received another error

[ts]
Type '({ data }: ImageListProps & { children?: ReactNode; }) => Element[]' is not assignable to type 'StatelessComponent<ImageListProps>'.
  Type 'Element[]' is not assignable to type 'ReactElement<any> | null'.
    Type 'Element[]' is not assignable to type 'ReactElement<any>'.
      Property 'type' is missing in type 'Element[]'.
const ImageList: React.StatelessComponent<ImageListProps>

I'm new to typescript and feel like I am missing some key things. Any ideas?

like image 251
user1507889 Avatar asked Jan 03 '23 09:01

user1507889


1 Answers

The error is a bit obscure, but the problem is that your function returns an array of ReactElement's instead of just one (returning an array will be allowed in react 16). If you wrap it in a parent div it should work:

const ImageList : React.SFC<ImageListProps> = ({data}) => (
  <div>
    { data.map(item => (
        <div key={item.post_url}>
          <a href={item.post_url}>{item.post_url}</a>
          <img src={item.image_url} />
          <h1>item.count</h1>
        </div>
    ))}
  </div>
);

(also removed a couple of redundant return statements)

like image 86
Oblosys Avatar answered May 23 '23 02:05

Oblosys