Felipe Cruz
Felipe Cruz

Reputation: 13

TypeError: Cannot read properties of undefined (reading 'map') Table.render

Trying to display a filtered table, but unsuccessful, see below.

Keep getting an undefined error when reading map, can't seem to figure out why colleges aren't being passed when calling on filteredColleges.map(college)

Could this possibly be because I'm calling on the <Table/> component inside my App.js and forgot a basic step?

App.js looks like so:

  return (
    <div className="App">
      <header className="App-header">
        <h1>Partners</h1>
        <Table/>
      </header>
    </div>
  );
}

If anyone could help I'd be very, very grateful. Thanks in advance!

import React , {Component } from 'react'

export default class Table extends Component {

// Display API data - componentDidMount - pull specific elements - DONE
// Create table displaying API data
// Create Search bar
// Create drop down list for prefix
// Style Ofsted Rating column

    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            colleges: [],
            searchByName: ""
        };
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        this.setState({ searchByName: event.target.value });
    }

    componentDidMount() {
        fetch(`https://collegesapi/data.json`)
        .then(res => res.json())
        .then(
            (result) => {
                this.setState({
                    isLoaded: true,
                    colleges: result.getColleges
                });
            },
            (error) => {
                this.setState({
                    isLoaded: true,
                    error
                });
            }
        )
    }

    renderRow(college) {
        return (
            <tr key={college.id}>
                <td>{college.name}</td>
                <td>{college.groupPrefix}</td>
                <td>
                    {college.logo && (
                        <img className="w-full" src={college.logo} alt={college.name} />
                    )} 
                </td>
                <td>{college.ofstedRating}</td>
            </tr>
        )
    }

    render() {

        const filterColleges = (colleges, query) => {
            if(!query) {
                return colleges;
            }

            return colleges.filter((college) => {
                const collegeName = college.name.toLowerCase();
                return collegeName.includes(query);      
            });
        };

        const filteredColleges = filterColleges(
            this.props.colleges,
            this.state.searchByName
        );

        const { error, isLoaded, colleges } = this.state;

        if (error) {
            return <div>Error: {error.message}</div>
        } else if (!isLoaded) {
            return <div>Loading...</div>;
        } else {
            return ( 
                <div>

                <table className="table-fixed border-collapse">
                        <thead>
                            <tr>
                                <input
                                    type="text"
                                    placeholder="Search partners"
                                    onChange={this.handleChange}
                                />
                            </tr>
                            <tr>
                                <th className="w-1/12">Partner</th>
                                <th className="w-1/12">Prefix</th>
                                <th className="w-1/12">Logo</th>
                                <th className="w-1/12">Ofsted Rating</th>
                            </tr>
                        </thead>
                        <tbody>{filteredColleges.map((college) => this.renderRow(college))}</tbody>
                    </table>
                </div>
            )
        }
    }
}

Upvotes: 1

Views: 4463

Answers (1)

Sujit Singh
Sujit Singh

Reputation: 921

You are referring this.props.colleges while sending to "filterColleges" function:

const filteredColleges = filterColleges(
  this.props.colleges,
  this.state.searchByName
);

Instead, since you are setting it in states when received from API response, you should refer accordingly:

const filteredColleges = filterColleges(
  this.state.colleges,
  this.state.searchByName
);

Also, it is always good to handle error or empty responses, for example, if your API does not return even empty array, then this code will still throw the same error. So you can add null coalescing checks (??) and assign empty array in these cases, as shown below:

this.setState({
        isLoaded: true,
        colleges: result?.getColleges ?? [],
      });

Hope it helps!

Upvotes: 2

Related Questions