上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染

Posted

技术标签:

【中文标题】上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染【英文标题】:componentDidMount() State Change in Context Provider not triggering re-render on Child Components 【发布时间】: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里面的代码有点不清楚,拿出了很多本来想做的事情。让我重新发布有效的方法。 【参考方案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 ;

【讨论】:

以上是关于上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

React - 上下文提供程序中的多个不相关值

上下文提供程序中的 componentDidMount() 状态更改未触发子组件的重新渲染

将路径参数传递给 React 上下文提供程序

链接多个上下文提供程序在反应本机的同一领域工作

中间件未解决测试 binance 提供程序中的 ExtraDataLengthError,导致未知帐户

魔法? React 上下文提供者从何而来?命名约定?