1

At this moment I'm trying to build a frontend page with a combination of React and TypeScript. What I'm trying to do is to fetch the "words" via a get method of axios and assign the data to an array, and then display it on the frontend page, which is fairly simple. I've already made sure that the backend part works fine using Postman.

As I didn't find a good "React & TypeScript" tutorial that exactly matches what I want to do, I'm studying with a "React & JavaScript" tutorial. What I find a little odd is that the completely valid part written in "React & JavaScript" causes an error "TypeError: this.state.wordsData.map is not a function" in my case, which is written in "React & TypeScript".

Here is my code.

import React from 'react';
import axios from 'axios'
import Word from '../interfaces/Word.interface';

class Home extends React.Component{

  state = {
    wordsData:new Array<Word>()
  }

  componentWillMount(){
    axios.get('http://localhost:8080/pictionarizerservices/api/words')
    .then(res => {
      const data = res.data;
      console.log("The content of res: ");
      console.log(res);
      this.setState({
        wordsData:{
          id: data.id,
          ownLangWordName: data.ownLangWordName,
          targetLangWordName: data.targetLangWordName,
          ownLangExSentence: data.ownLangExSentence,
          targetLangExSentence: data.targetLangExSentence,
          createdDate: data.createdDate
        }
      })
    })
  }

  render(){
    return(
      <div>
        <h2>Words:</h2>
        <table>
        <thead>
          <tr>
          <th>ID</th>
          <th>Word (OL)</th>
          <th>Word (TL)</th>
          <th>Sentence (OL)</th>
          <th>Sentence (TL)</th>
          <th>Created Date</th>
          </tr>
        </thead>
        <tbody>
          {this.state.wordsData.map(singleWord=>
          <RowCreator 
            id={singleWord.id}
            ownLangWordName={singleWord.ownLangWordName}
            targetLangWordName={singleWord.targetLangWordName}
            ownLangExSentence={singleWord.ownLangExSentence}
            targetLangExSentence={singleWord.targetLangExSentence}
            createdDate={singleWord.createdDate}
            />)}
        </tbody>
        </table>
      </div>
    )
  }
}

class RowCreator extends React.Component<Word>{

  render(){
    let word = this.props;
    return(
        <tr>
          <td>{word.id}</td>
          <td>{word.ownLangWordName}</td>
          <td>{word.targetLangWordName}</td>
          <td>{word.ownLangExSentence}</td>
          <td>{word.targetLangExSentence}</td>
          <td>{word.createdDate}</td>
        </tr>
    )
  }
}

export default Home; 

I modified the syntax a little bit in order to adjust to TypeScript, but the followings are all I changed.

from

state = {
    patientData:[]
}

to

  state = {
    wordsData:new Array<Word>()
  }

,and from

class RowCreator extends React.Component{
...

to

class RowCreator extends React.Component<Word>{
...

That's all.

What I already know by studying by myself about TypeScript is that TypeScript is a strict superset of JavaScript, and all valid code written in JavaScript should be valid in TypeScript as well. Also, especially when writing in Visual Studio Code, TypeScript's error detecting feature is excellent and you'll find a lot more errors beforehand compared to when you are writing in JavaScript. I made sure that all the error markups were gone before running the program, and now I get this "TypeError: this.state.wordsData.map is not a function" error as a run time error.

How can I get the part

<tbody>
          {this.state.wordsData.map(singleWord=>
          <RowCreator 
            id={singleWord.id}
            ownLangWordName={singleWord.ownLangWordName}
            targetLangWordName={singleWord.targetLangWordName}
            ownLangExSentence={singleWord.ownLangExSentence}
            targetLangExSentence={singleWord.targetLangExSentence}
            createdDate={singleWord.createdDate}
            />)}
        </tbody>

to work in TypeScript?

2
  • Your setState in componentWillMount of the Home component assings an object to this.state.wordsData. Perhaps you meant to assign an array or push into the existing array. Commented Jun 14, 2020 at 14:22
  • Yes I meant to assign values as array but it turned out it was stored in a form of object without me realizing. Commented Jun 14, 2020 at 17:37

1 Answer 1

2

you are setting it to an object

  this.setState({
    wordsData:{
      id: data.id,
      ownLangWordName: data.ownLangWordName,
      targetLangWordName: data.targetLangWordName,
      ownLangExSentence: data.ownLangExSentence,
      targetLangExSentence: data.targetLangExSentence,
      createdDate: data.createdDate
    }
  })

set it to an array like so:

  this.setState({
    wordsData:[{
      id: data.id,
      ownLangWordName: data.ownLangWordName,
      targetLangWordName: data.targetLangWordName,
      ownLangExSentence: data.ownLangExSentence,
      targetLangExSentence: data.targetLangExSentence,
      createdDate: data.createdDate
    }]
  })
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the concrete example :) The error vanished after wrapping the object with square brackets just like you suggested.

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.