Javascript React JS-can';t对尚未安装的组件调用setState

Javascript React JS-can';t对尚未安装的组件调用setState,javascript,reactjs,rxjs,axios,Javascript,Reactjs,Rxjs,Axios,我在React JS中有我的应用程序。我正在从一个API获取数据http://localhost:8080/api/suppliers/supplier/list: 以下是我从Google Chrome控制台中的REST API获得的数据: 0:{ id: 4 supplierFirstname: "Tom" supplierLastName: "ABC" supplierTitle: "TomTheSupplie

我在React JS中有我的应用程序。我正在从一个API获取数据http://localhost:8080/api/suppliers/supplier/list:

以下是我从Google Chrome控制台中的REST API获得的数据:

0:{
    id: 4
    supplierFirstname: "Tom"
    supplierLastName: "ABC"
    supplierTitle: "TomTheSupplier"
    accountNumber: 1122234444
    address: "111 ADrive, 1234 ST."
    companyName: "TheTom Company & Associates"
    email: "tomtomjayjay@email.com"
    hourlyRate: 29
    phoneNumber: 123456789
    otherPhoneNumber: 1023456789
    paymentTerms: "Credit"
    notes: "Some Supplier"
    createdAt: null
    typeOfGoods: "Supplies"
    website: "www.abc_123.com"
    products: [{…}]
    components: 
        [
            0: {id: 5, name: "AComponent", unit: null, quantity: 0, componentCost: 0, …}
        ]
    
}
这是我的代码:

class SupplierData extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      supplier: [
        {
          id: 0,
          supplierTitle: "Supplier Title",
          supplierFirstName: "First Name",
          supplierLastName: "Last Name",
          companyName: "Company Name",
          phoneNumber: "Phone Number",
          otherPhoneNumber: "Phone Number (Other)",
          accountNumber: "Account Number",
          email: "Email",
          address: "Address",
          website: "Website",
          hourlyRate: "Hourly Rate",
          typeOfGoods: "Type Of Goods",
          paymentTerms: "Payment Terms",
          createdAt: "Created At",
          notes: "Notes",
          products: "Products",
          components: "Components",
        },
      ],
      errorMessage: [],
    };
    this.ListAllSuppliers = this.ListAllSuppliers.bind(this);
  }

  ListAllSuppliers = async () => {
    return await axios
      .get(`http://localhost:8080/api/suppliers/supplier/list`)
      .then((response) => {
        let apiResults = response.data;
        console.log(apiResults);
        this.setState({ supplier: apiResults });    <--- The error happens here.
      })
      .catch((error) => {
        this.setState({ errorMessage: this.state.errorMessage.push(error) });
      });
  };

  componentDidMount() {
    this.ListAllSuppliers();
  }
}

export default SupplierData;
问题: 我想设定状态


有什么方法可以修复上述错误?

代码本身基本上没有问题,尽管您混合了对
.then
的调用。catch
异步
/
wait
,这不是最佳做法,并且您对arrow函数不必要地使用了
绑定

听起来您的组件在启动
axios
调用之后和返回之前正在卸载,这导致您在未装载的组件上调用
setState
。(尽管错误的措辞与我看到的略有不同。)

为了避免这种情况,您可以通过在选项中传递
cancelToken
并在
componentWillUnmount
source
上使用
cancel
方法,从
componentWillUnmount
调用axios。(内置提供了相同的功能,通过。)(如果您正在执行不支持取消的操作,作为回退,您可以设置
此项。在
组件中卸载的
将卸载
,然后检查此项,如果您看到
此项为真,则不调用
设置状态

代码还有一些其他问题;这是一个更新的版本,上面提到了cancel令牌以及其他内联解决的问题(请参阅注释):


乍一看很好…从构造函数中删除这一行
this.listallproviders=this.listallproviders.bind(this)。您不需要此功能,因为
listalsuppliers
是一个箭头函数HI,欢迎使用SO!碰巧您在这个问题中添加了不相关的标记。标签
node.js
rxjs
与问题主题无关。请考虑一个标签可能与你的特定问题无关,即使它与你的项目相关。@托马斯-谢谢!我搜索“信号”是因为。(我还搜索了“abort”,并认为我搜索了[我喜欢的词]“cancel”,但显然不是!)@abc_123-上面的调用非常简单。如果您没有在后端看到它,那么这是一个与此问题无关的后端问题。我希望你能弄明白!
Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might 
         indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = 
         {};` class property with the desired state in the SupplierData component.
class SupplierData extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            supplier: [
                {
                    id: 0,
                    supplierTitle: "Supplier Title",
                    supplierFirstName: "First Name",
                    supplierLastName: "Last Name",
                    companyName: "Company Name",
                    phoneNumber: "Phone Number",
                    otherPhoneNumber: "Phone Number (Other)",
                    accountNumber: "Account Number",
                    email: "Email",
                    address: "Address",
                    website: "Website",
                    hourlyRate: "Hourly Rate",
                    typeOfGoods: "Type Of Goods",
                    paymentTerms: "Payment Terms",
                    createdAt: "Created At",
                    notes: "Notes",
                    products: "Products",
                    components: "Components"
                },
            ],
            errorMessage: [],
        };
        // No need to bind `listAllSuppliers`, you don't use it as a callback

        // A single cancel source that can cancel multiple operations
        this.cancelSource = axios.CancelToken.source();
    }

    // Use an async method
    // Note the initial lower case `l` (not `L`), which is standard in JavaScript
    async listAllSuppliers() {
        // In an `async` function, you use `try`/`catch` and `await`, not
        // `.then` / `.catch` methods
        try {
            const response = await axios.get(
                `http://localhost:8080/api/suppliers/supplier/list`,
                {cancelToken: this.cancelSource.token}
            );
            const supplier = response.data;
            console.log(supplier)
            this.setState({supplier});
        } catch (error) {
            // Updating state based on existing state requires the callback form
            // of `setState` , and you must never directly modify state objects
            this.setState(({errorMessage}) => ({
                errorMessage: [...errorMessage, error]
            }));
        }
    }

    componentDidMount() {
        this.listAllSuppliers();
    }

    componentWillUnmount() {
        // Cancel any outstanding axios calls
        this.cancelSource.cancel("Component unmounted");
    }

    // Presumably you do have a `render` method, you'd get a different React error if you didn't
    render() {
        // ...
    }
}

export default SupplierData;