代码之家  ›  专栏  ›  技术社区  ›  TechSavy

修改状态数组中的任何值时,ReactJS组件状态未更新

  •  3
  • TechSavy  · 技术社区  · 6 年前

    import React, { Component } from "react";
    import { Link } from "react-router-dom";
    import axios from "axios";
    import $ from "jquery";
    import isEqual from "lodash/isEqual";
    $.DataTable = require("datatables.net");
    
    class Active extends Component {
      state = {
        activeData: [],
        flag: 0,
        isLoading: true
      };
    
      componentDidMount() {
        this.getActiveData();
      }
    
      componentDidUpdate(prevProps, prevState) {
        if (!isEqual(prevState.activeData, this.state.activeData)) {
          this.getActiveData();
        }
      }
    
      getActiveData() {
        const params = new FormData();
        params.append("status", "active");
        axios.post("http://127.0.0.1:8000/details/", params).then(res => {
          if (res.data.result === 1) {
            this.setState({
              activeData: res.data.data,
              flag: 1,
              isLoading: false
            });
            if (!this.state.isLoading) {
              this.initTable();
            }
          } else if (res.data.result === 0) {
            this.setState({ isLoading: false });
            this.initTable();
          }
        });
      }
    
      initTable() {
        $("#Active_Datatable").DataTable();
      }
    
      render() {
        if (this.state.isLoading) {
          return (
            <img
              alt="loading"
              src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif"
            />
          );
        }
        return (
          <React.Fragment>
            <div className="panel-heading" role="tab" id="heading3">
              <a
                href="#Current"
                className="collapsed text-left textuppercase"
                role="button"
                data-toggle="collapse"
                data-parent="tabs-content"
                aria-expanded="true"
                aria-controls="Current"
              >
                <i className="fas fa-list-ul" /> Current
                <i className="fas fa-chevron-down pull-right" />
              </a>
            </div>
    
            <div
              id="Current"
              role="tabpanel"
              className="tab-pane panel-collapse collapse"
              aria-labelledby="heading3"
            >
              <table
                id="Active_Datatable"
                className="display"
                style={{ width: "100%" }}
              >
                <thead>
                  <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Open</th>
                    <th>Close</th>
                    <th>Price</th>
                  </tr>
                </thead>
                {this.state.flag === 1 ? (
                  <tbody>
                    {this.state.activeData.map((ac, i) => (
                      <tr key={sc.id}>
                        <td className="text-center">{i + 1}</td>
                        <td>
                          <Link
                            to={{
                              pathname: `/${ac.name_slug}/`,
                              state: {
                                id: ac.id,
                                name: ac.name
                              }
                            }}
                          >
                            {sc.name}
                          </Link>
                        </td>
                        <td>{sc.open_date}</td>
                        <td>{sc.close_date}</td>
                        <td>
                          {Number(sc.price).toLocaleString("en-IN", {
                            currency: "INR"
                          })}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                ) : null}
              </table>
            </div>
          </React.Fragment>
        );
      }
    }
    
    export default Active;
    

    这个 lodash.isequal 在里面 componentDidUpdate() 方法没有更新我的状态。

    我还在componentDidUpdate中尝试了以下逻辑:

    componentDidUpdate(prevProps, prevState) {
        if (prevState.activeData !== this.state.activeData) {
          this.getActiveData();
        }
    }
    

    提前谢谢!

    **在等待这个问题的解决方案。

    从所有的答案来看,我想我应该用例子来解释。所以当我调用API并更新state时 activeData ,更新为:

    [
     {
       id: 1
       name: "ABC"
       close_date: "2019-01-11"
       open_date: "2019-01-08"
       price: "80"
     },
     {
       id: 2
       name: "XYZ"
       close_date: "2019-01-12"
       open_date: "2019-01-04"
       price: "80"
     }
    ]
    

    例如,如果我从 ABC ABCD 返回的结果将是:

    [
     {
       id: 1
       name: "ABCD"
       close_date: "2019-01-11"
       open_date: "2019-01-08"
       price: "80"
     },
     {
       id: 2
       name: "XYZ"
       close_date: "2019-01-12"
       open_date: "2019-01-04"
       price: "80"
     }
    ]
    

    这两种情况都不会发生 shouldComponentUpdate 或者按照建议修改我的lodash语法。

    目录结构:

    project
      |- public
      |- src
         -components
            -Header_Footer
              Header.jsx
              Footer.jsx
            -Home
              index.jsx
              -Details
                 Active.jsx
                 Upcoming.jsx
         App.js
         index.js    
    

    import React, { Component } from "react";
    import Active from "./Active";
    import Upcoming from "./Upcoming";
    
    class Details extends Component {
    
      render() {
        return (
          <div className="col-md-9 col-sm-9 col-xs-12">
            <div className="right_panel">
              <h2>Listing</h2>
    
              <div className="responsive-tabs text-center ">
                <ul className="nav nav-tabs" role="tablist">
                  <li role="presentation" className="active">
                    <a
                      href="#Upcoming"
                      aria-controls="Upcoming"
                      role="tab"
                      data-toggle="tab"
                    >
                      Upcoming
                    </a>
                  </li>
                  <li role="presentation" className="">
                    <a
                      href="#Current"
                      aria-controls="Current"
                      role="tab"
                      data-toggle="tab"
                    >
                      Current
                    </a>
                  </li>
    
                </ul>
                <div
                  id="tabs-content"
                  className="tab-content panel-group table-responsive"
                >
                  <Upcoming />
                  <Active />
                </div>
              </div>
            </div>
          </div>
        );
      }
    }
    
    export default Details;
    

    主页.js

    import React, { Component } from "react";
    import Sidebar from "./Sidebar";
    import Details from "./details";
    
    class Home extends Component {
    
      render() {
        return (
          <div className="container container_padding">
            <div className="row">
              <Sidebar />
              <Details />
            </div>
          </div>
        );
      }
    }
    
    export default Home;
    

    应用程序.js

    import React, { Component } from "react";
    import { Router, Route, Switch } from "react-router-dom";
    import Header from "./components/Header_Footer/Header";
    import Footer from "./components/Header_Footer/Footer";
    import Home from "./components/Home";
    import createBrowserHistory from "history/createBrowserHistory";
    const history = createBrowserHistory();
    
    class App extends Component {
      render() {
        return (
          <Router history={history}>
            <React.Fragment>
              <Header />
              <Switch>
                <Route exact path="/" component={Home} />
              </Switch>
              <Footer />
            </React.Fragment>
          </Router>
        );
      }
    }
    
    export default App;
    
    4 回复  |  直到 6 年前
        1
  •  0
  •   Krina Soni    6 年前

    我想你有一些语法错误 Lodash Docs ,则需要在函数之前添加下划线。

    尝试执行以下操作:

    if (!_.isEqual(prevState.activeData, this.state.activeData)) {
          this.getActiveData();
        }
    

    另外,请检查两个数组是否唯一,是否正在进行比较。这就是你的问题所在。

        2
  •  0
  •   Shalini Sentiya    6 年前
     you can also use the lodash package from this 
     https://www.npmjs.com/package/lodash
    
     $ npm i --save lodash        
    
     import isEqual from "lodash/isEqual";
    
     componentDidUpdate(prevProps, prevState) {
       if (!isEqual(prevState.activeData, this.state.activeData)) {
          this.getActiveData();
       }
     }
    
        3
  •  0
  •   Shalini Sentiya    6 年前
    isEqual method is working Properly, You have need to change componentDidUpdate() method from getSnapshotBeforeUpdate() method because componentDidUpdate(prevProps, prevState) method execute after update the state so prevState having the same value which are having the this.state.activeData.
    
    getSnapshotBeforeUpdate(prevProps, prevState) {
        if (!isEqual(prevState.activeData, this.state.activeData)) {
          this.getActiveData();
        }
        return null;
      }
    
        4
  •  0
  •   Kyaw Kyaw Soe    6 年前

    getActiveData componentDidUpdate 只会在第一次发生componentDidUpdate时调用一次,并且不会再次调用它,因为 prevState.activeData 永不改变。

    getActiveData() 组件更新 组件更新 shouldComponentUpdate 为了决定该组件是否应该更新,这里的代码

    componentDidMount() {
        this.getActiveData();
    }
    
    shouldComponentUpdate(nextProps, nextState){
       return !isEqual(nextState.activeData, this.state.activeData)
    }
    
    componentDidUpdate() {
        this.getActiveData();
    }