【问题标题】:React and jquery-ui/ui/widgets/sortable: Child component not reorder as expectReact 和 jquery-ui/ui/widgets/sortable:子组件未按预期重新排序
【发布时间】:2020-07-04 13:38:05
【问题描述】:

我在父组件的“状态”中有一个名为“组合”的数组。您可以使用:“this.state.portfolios”访问。

还有一个名为“StockDetailsComponent”的子组件。

在父组件中,我使用 map 函数来渲染子组件“StockDetailsComponent”,如下所示:

  {
    this.state.portfolios.map((obj, key) => {
      return <StockDetailsComponent key={key} portfolio={obj} onRemovePortfolio={this.onRemovePortfolio}/>;
    })
  }

没关系。但是当我重新排序“this.state.portfolios”时,子组件重新渲染的结果不如预期。

之前:投资组合 = ["object_stock_symbol_1", "object_stock_symbol_2"];

重新排序后:portfolis = ["object_stock_symbol_2", "object_stock_symbol_1"];

父组件如下所示,让我解释一下:

 class VndDomain extends React.Component {
  constructor(props) {
    super(props);
    this.socket = null;
    this.sortableEnabled = false;
    this.state = {
      portfolios: []
    };
  }

  render() {
    return (
      <div id="SQ-vnd">
        <HeaderComponent/>

        <div className="SQ-body">
          <div className="SQ-text-right">
            <p className="SQ-d-inline-block SQ-cursor-pointer SQ-mt-5 SQ-mb-5" onClick={this.removeAllPortfolios}>Xóa toàn bộ</p>
          </div>

          <StockFormCreateComponent onCreatePortfolio={this.onCreatePortfolio}/>

          <div id="JSSQ-portfolio">
            {
              this.state.portfolios.map((obj, key) => {
                return <StockDetailsComponent key={key} portfolio={obj} onRemovePortfolio={this.onRemovePortfolio}/>;
              })
            }
          </div>

        </div>

        <FooterComponent/>
      </div>
    );
  }

  componentDidMount() {
    this.enableSortable();
    this.getAllPortfolioByUserId();
  }

  /**
   * Get all portfolios belong to current user
   * @return {Promise} [description]
   */
  getAllPortfolioByUserId = async () => {
    try {
      this.props.dispatch(loadingSpinnerActions.showLoadingSpinner());
      let result = await PortfolioService.getAllPortfolioByUserId();
      if(result.data.status === "SUCCESSFUL") {
        this.setState({portfolios: result.data.data}, () => {
          this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
        });
      } else {
        throw new Error(`${result.data.message}`);
      }
    } catch(error) {
      this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
      CommonUtilities.ShowLog(error.message);
    }
  }

  /**
   * Enable drag and drop to reorder
   * @return {[type]} [description]
   */
  enableSortable = () => {
    let parentEl = $("#JSSQ-portfolio");
    // Check duplicate sortable before set
    if (this.sortableEnabled) {
      parentEl.sortable("destroy");
      parentEl.sortable();
    } else {
      parentEl.sortable();
      this.sortableEnabled = true;
    }

    parentEl.on("sortupdate", async () => {
      let sorted = parentEl.sortable("serialize");
      let newOrderArrObj = sorted.split("&").map((value) => {
        let symbol = value.replace("SQ[]=", "").toUpperCase();
        let portfolio = this.state.portfolios.find(obj => obj.symbol === symbol);
        return {
          _id: portfolio._id,
          symbol
        };
      });

      try {
        this.props.dispatch(loadingSpinnerActions.showLoadingSpinner());
        let result = await PortfolioService.reorderPortfolio({newOrder: newOrderArrObj});
        if(result.data.status === "SUCCESSFUL") {
          this.setState({portfolios: result.data.data}, () => {
            this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
          });
        } else {
          throw new Error(`${result.data.message}`);
        }
      } catch(error) {
        this.setState((prevState) => {
          return {portfolios: prevState.portfolios};
        }, () => {
          this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
        });
      }

    });
  }

首先,我从数据库中获取列表投资组合,分配给状态的“投资组合”,显示在客户端中。并通过“enableSortable”功能启用拖放以重新排序。目前,它工作正常。

当我拖动重新排序时,“this.state.portfolios”按预期更改,我可以在“console.log()”中看到,但子组件渲染错误。不按顺序。

代码很长,所以你只需要注意我尝试的以下选项: 选项 1:

this.setState({portfolios: result.data.data}, () => {
  this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
});

result.data.data 是重新排序后的数据,可以,但是重新渲染不能按顺序工作。

选项 2:如果我通过空数组清除状态并像下面的代码一样再次设置它,它是有效的,因为子组件已经“卸载”并重新渲染,而不是像选项 1 一样更新。

 this.setState({portfolios: []}, () => {
   this.setState({portfolios: result.data.data}, () => {
     this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
   });
 });

请帮帮我:(我不想先设置状态,然后再设置状态。

【问题讨论】:

    标签: javascript reactjs jquery-ui-sortable


    【解决方案1】:

    看起来你的投资组合数据是一个复杂的对象,React 无法确定它已经改变了。你可以这样做:

    你可以这样做:

    let newPrtfolio = Object.assign ([],result.data.data); // Assign data to new object and assign it
    
    this.setState({portfolios: newPrtfolio }, () => {
      this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
    });
    

    或者如果你的投资组合是一个对象而不是一个数组,那么你可以尝试以下方式:

     let newPrtfolio = Object.assign ({},result.data.data); // Assign data to new object and assign it
        
        this.setState({portfolios: newPrtfolio }, () => {
          this.props.dispatch(loadingSpinnerActions.hideLoadingSpinner());
        });
    

    你可以尝试这两种方法,其中一种会根据你的投资组合对象的结构为你解决

    【讨论】:

    • 另外,如果您的投资组合是一个对象而不是一个数组,那么您可以将 newportfolio 设置为: let newPrtfolio = Object.assign ({},result.data.data); .所以,你可以尝试两种方式
    • @Xuan 对你有帮助吗?
    • 它是对象数组。我试过了,但它仍然给出相同的结果。 :(
    • 你能在codeSandbox上给出一个工作代码来调试问题吗?
    • 谢谢大家,等我上传沙盒
    猜你喜欢
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    • 2022-08-17
    • 2019-04-06
    • 2011-02-25
    • 1970-01-01
    相关资源
    最近更新 更多