user3802564
user3802564

Reputation: 169

componentDidMount() State Change in Context Provider not triggering re-render on Child Components

Here is my code. Been trying to get this to work for 4 days now. I've tried everything from function Components to class Components, to everything in between. At my wits' end. I can't set the state properly in the constructor because it's asynchronous but it doesn't re-render when put in componentDidMount()

EDIT: Yes i know some of the code is redundant. I changed it around to isolate the bug and removed the addParams() logic as well as some other things.

    import React, { Component } from "react";
import axios from "axios";
export const ListContext = React.createContext();

class ListContextProvider extends Component {
  constructor() {
    super();
    this.state = { cards: {}, params: {} };
  }

  addParams(parameters) {
    return parameters;
  }

  getCards() {
    let parameters = this.addParams({ last_name__icontains: "smith" });
    console.log(parameters);
    axios({
      method: "get",
      url: "http://127.0.0.1:8000/charges/cardsapi/",
      params: parameters,
    }).then((response) => {
      let cards = Object.values(response.data.results);
      let cardsState = Object.assign({}, cards);
      this.setState({ cards: cardsState });
      console.log(this);
      console.log(this.state);
    });
  }

  componentDidMount() {
    console.log("mounted");
    this.getCards();
  }

  render() {
    return (
      <ListContext.Provider value={this.state}>
        {this.props.children}
      </ListContext.Provider>
    );
  }
}

export { ListContextProvider };

and then the Consumer:

export default function DataTable(context) {
  let cards = context;

  const rows = [];
  const headerCells = [];
  if (cards.length > 1) {
    for (let field in cards[0]) {
      headerCells.push(<TableCell key={field}>{field}</TableCell>);
    }

    for (let row of cards) {
      const cells = [];
      for (const [key, value] of Object.entries(row)) {
        cells.push(<TableCell key={key}>{value}</TableCell>);
      }
      rows.push(<TableRow key={cells[0].props.children}>{cells}</TableRow>);
    }

    return (
      <Table>
        <TableHead>
          <TableRow key={"header"}>{headerCells}</TableRow>
        </TableHead>
        <TableBody>{rows}</TableBody>
      </Table>
    );
  } else {
    return (
      <Table>
        <tbody>
          <tr>
            <td>Empty</td>
          </tr>
        </tbody>
      </Table>
    );
  }
}

Upvotes: 1

Views: 505

Answers (1)

user3802564
user3802564

Reputation: 169

This worked:

import React, { Component } from "react";
import axios from "axios";

let ListContext = React.createContext();


class ListContextProvider extends Component {
  constructor() {
    super();
    this.state = { cards: [], params: {} };
  }

  addParams(parameters) {
    this.setState({ params: parameters });
  }

  getCards() {
    let parameters = this.state.params;
    console.log(parameters);
    axios({
      method: "get",
      url: "http://127.0.0.1:8000/charges/cardsapi/",
      params: parameters,
    }).then((response) => {
      let cardsState = Object.values(response.data.results);
      this.setState({ cards: cardsState });
    });
  }

  async componentDidMount() {
    await this.addParams({ last_name__icontains: "shaer" });
    console.log("mounted");
    this.getCards();
  }

  render() {
    return (
      <ListContext.Provider value={this.state}>
        {this.props.children}
      </ListContext.Provider>
    );
  }
}

export { ListContextProvider, ListContext };

Upvotes: 2

Related Questions