简体   繁体   中英

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>
            )
        }
    }
}

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM