4

I am exploring React and Typescript and I stuck on a problem of how to define an interface for an array where are stored data from an API.

Here's what I have:

interface IState {
  loadingData: boolean;
  apiData: Array<string>;
}

class Contact extends Component<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      loadingData: true,
      apiData: []
    };
  }

  componentDidMount() {
    const apiUrl = 'http://jsonplaceholder.typicode.com/users';
    fetch(apiUrl)
      .then((response) => response.json())
      .then((data) => {
        console.log('This is your data', data);
        this.setState({ loadingData: false, apiData: data });
      })
      .catch(error => console.log('error: ', error));
  }
  ...

After running this code, though, I receive the following error:

Error: Objects are not valid as a React child (found: object with keys {id, name, username, email, address, phone, website, company}). If you meant to render a collection of children, use an array instead.
    in div (at Contact.tsx:39)
    in div (at Contact.tsx:33)
    in Contact (created by Context.Consumer)
    in Route (at Main.tsx:26)
    in div (at Main.tsx:23)
    in div (at Main.tsx:16)
    in Router (created by HashRouter)
    in HashRouter (at Main.tsx:15)
    in Main (at src/index.tsx:9)

What's the key to properly set up an interface for an array?

EDIT: Adding the render function:

render() {
    return (
      <div>
        <div>
          <h5>API Data</h5>
          {this.state.loadingData ? (
              'Loding data...'
            ) : (
              this.state.apiData
            )
          }
        </div>
      </div>
    );
  }
4
  • 3
    please post the render function, where the error is located Commented Jul 16, 2020 at 12:41
  • @Jerome added, thanks. Commented Jul 16, 2020 at 12:47
  • This is more or less a duplicate of stackoverflow.com/q/40746168/691711. Commented Jul 16, 2020 at 12:53
  • in render, it should {this.state.apidata && this.state.apiData.map((data:IApiData) =>{ return (<div key={data.id}>{data.whatever}</div> } Commented Jul 16, 2020 at 15:17

1 Answer 1

2

You can't render an array in react.

{this.state.loadingData ? (
   'Loding data...'
  ) : (
    this.state.apiData 
     && this.state.apiData.map(item => <p key={item.id}>{item.name}</p>
  )
}

this.state.apiData && this.state.apiData.map will check if apiData exists (not falsy, this won't protect you from it being a wrong type) and then run call the map.

And you need to update your interface

interface IState {
  loadingData: boolean;
  apiData: ApiData[];
}

interface ApiData {
  id: string
  name: string
  ...
}
Sign up to request clarification or add additional context in comments.

Comments

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.