【问题标题】:componentDidMount() State Change in Context Provider not triggering re-render on Child Components上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染
【发布时间】:2020-11-06 14:12:44
【问题描述】:

这是我的代码。一直试图让它工作4天。从函数组件到类组件,再到介于两者之间的所有东西,我都尝试过。不知所措。我无法在构造函数中正确设置状态,因为它是异步的,但是在放入 componentDidMount() 时不会重新渲染

编辑:是的,我知道有些代码是多余的。我对其进行了更改以隔离错误并删除了 addParams() 逻辑以及其他一些内容。

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

然后是消费者:

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

【问题讨论】:

  • 我建议将 onLoad 标志添加到 ListContextProvider 组件的状态。只有在 axios 返回时,它才会变为 true。在渲染器函数中,您在数据不可用时返回 - 或做任何事情。但请确保仅在数据可用时渲染
  • 我认为这是个好建议。这就是我要尝试的。谢谢。
  • 我使用 useContext() 钩子解决了这个问题。我不知道为什么 Consumer Context 不起作用,但无论如何钩子更干净。
  • 你确定你引用了正确的this吗?您正在为rendercomponentDidMount 使用普通函数,因此它们有自己的this 上下文。
  • 哦是的,即使在嵌套的axios调用中this也绑定了ListContextProvider对象。它确实呈现正确,只是没有更新状态更改。我能够使用useContext() 钩子和等待addParams() 完成状态更新的异步componentDidMount() 来解决这个问题。 OP里面的代码有点不清楚,拿出了很多本来想做的事情。让我重新发布有效的方法。

标签: javascript reactjs react-hooks react-component react-context


【解决方案1】:

这行得通:

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

【讨论】:

    猜你喜欢
    • 2019-10-30
    • 2020-06-26
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多