Search code examples
jsonreactjstypescriptaxiosapi-design

How do I make my table dynamically change based on year?


I'm trying to populate a table with some information pulled from my database through an API based on year. I'm using React Router and would like to keep my sidebar with the links to different years, but dynamically change the table that is the main focus of this page.

I can get the Table to render with the first year(2019, since this is the default link), but that's only if it's outside the <Switch>. This also causes the problem that it doesn't change when the link changes.

class YearlyTable extends React.Component {
    state = {
        yearlyTable: [],
        isLoading: false,
    }

    componentDidMount() {
        this.setState({ isLoading: true });
        axios.get(
            `http://localhost/yearTable/${this.props.match.params.yearId}${this.props.location.search}`,
            { withCredentials: true }
        ).then(res => {
            const yearlyTable = res.data;
            this.setState({ yearlyTable, isLoading: false });
        }).catch((error) => {
            console.log(error);
        });
    }
    render() {
        // isLoading component

        // Check what API returns
        console.log(this.state.yearlyBonds);

        return (
            // Removed for simplicity
                    // This returns a table
                    {this.state.yearlyTable && <ListTable title={this.state.yearlyTable.Title} data={this.state.yearlyTable.Bonds} />}
                        // This does not
                        <Switch>
                           <Route exact path={`/yearly_table/${this.props.match.params.yearId}${this.props.location.search}`} render={() => this.state.yearlyTable && <ListTable title={this.state.yearlyTable.Title} data={this.state.yearlyTable} />} />
                        </Switch>
                    // Sidebar removed for simplicity
        );
    }
}
export default withRouter(YearlyTable);

The outcome I'm wanting to achieve is that it renders the first table, but when you press one of the links, then it changes out the table with the new contents.


Solution

  • This is happening because you are using componentDidMount. This is called only for the first render, not after that.

    You can do something like

        class YearlyTable extends React.Component {
            state = {
                yearlyTable: [],
                isLoading: false,
            }
    
            componentDidMount() {
                this.setState({ isLoading: true });
                axios.get(
                    `http://localhost/yearTable/${this.props.match.params.yearId}${this.props.location.search}`,
                    { withCredentials: true }
                ).then(res => {
                    const yearlyTable = res.data;
                    this.setState({ yearlyTable, isLoading: false });
                }).catch((error) => {
                    console.log(error);
                });
            }
    
    updateData(){
                 axios.get(
                    `http://localhost/yearTable/newYearID${this.props.location.search}`,
                    { withCredentials: true }
                ).then(res => {
                    const yearlyTable = res.data;
                    this.setState({ yearlyTable, isLoading: false });
                }).catch((error) => {
                    console.log(error);
                });
    }
            render() {
                // isLoading component
    
                // Check what API returns
                console.log(this.state.yearlyBonds);
    
                return (
                    // Removed for simplicity
                            // This returns a table
                            {this.state.yearlyTable && <ListTable title={this.state.yearlyTable.Title} data={this.state.yearlyTable.Bonds} />}
                           <Link onClick={this.updateData.bind(this, clickedItemYear)}>Some Item</Link>
                );
            }
        }
        export default withRouter(YearlyTable);
    

    You can use and preventDefault or stopPropogation of the event. Better make a function call , so that it is called again whenever there is some user action.