繁体   English   中英

如何更改作为列传递给 React Table 的子组件道具的值?

[英]How to change the value of a prop of Sub Component passed as a column to React Table?

我在 Web 应用程序中使用React 表库。

我将一个组件作为列传递给表。 表格的列和数据如下所示。

  columns = [
    {
      Header: "Name",
      accessor: "name"
    },
    {
      Header: "Action",
      accessor: "action"
    }
  ];

  sampleData = [
    {
      id: 1,
      name: "Product one",
      action: (
        <TestComponent
          id={1}
          inProgress={false}
          onClickHandler={id => this.onClickHandler(id)}
        />
      )
    },
    {
      id: 2,
      name: "Product two",
      action: (
        <TestComponent
          id={2}
          inProgress={false}
          onClickHandler={id => this.onClickHandler(id)}
        />
      )
    }
  ];

我的TestComponent如下所示。

const TestComponent = ({ id, inProgress, onClickHandler }) => {
  return (
    <div>
      {inProgress ? (
        <p>In Progress </p>
      ) : (
        <button onClick={() => onClickHandler(id)}>click me</button>
      )}
    </div>
  );
};

我的目的是,当用户单击click me按钮时,它需要调用Backend API 那时inProgress道具需要为true ,它应该传递到表格并需要文本作为正在进行中,直到 API 调用完成。

我可以改变state如下。

  onClickHandler(id) {
    const newData = this.sampleData.map(data => {
      if (data.id === id) {
        return {
          ...data,
          action: (
            <TestComponent
              id={1}
              inProgress={true}
              onClickHandler={id => this.onClickHandler(id)}
            />
          )
        };
      }
      return data;
    });
    this.setState({ data: newData });

    // Here I Call the Backend API and after complete that need to show the click me button again.
    setTimeout(() => {
      this.setState({ data: this.sampleData });
    }, 3000);
  }

我可以实现我所需要的但我对更改state的方式不满意。 我需要知道是否有更好的方法来做到这一点,而无需像这样更改state

您可以使用此StackBlitz Link 为我提供更好的解决方案。 谢谢。

您可以在TestComponent中维护一个本地 state ,而不是将inProgress道具传递给TestComponent ,用于确定是显示进度文本还是按钮,并且只将idonClickHanlder道具传递给TestComponent

When button is clicked in TestComponent , you could set the the local state of TestComponent to show the progress text and then call the onClickHandler function passed as prop, passing in the id prop and a callback function as arguments. 当 API 请求完成时,将调用此回调 function。 此回调 function 在TestComponent内部定义,仅切换TestComponent的本地 state 以隐藏进度文本并再次显示按钮。

将您的TestComponent更改为如下所示:

const TestComponent = ({ id, onClickHandler }) => {
  const [showProgress, setShowProgress] = React.useState(false);

  const toggleShowProgress = () => {
    setShowProgress(showProgress => !showProgress);
  };

  const handleClick = () => {
    setShowProgress(true);
    onClickHandler(id, toggleShowProgress);
  };

  return (
    <div>
      {showProgress ? (
        <p>In Progress </p>
      ) : (
        <button onClick={handleClick}>click me</button>
      )}
    </div>
  );
};

我使用useState挂钩来维护TestComponent的本地 state,因为它是一个功能组件,但您也可以在 class 组件中使用相同的逻辑。

sampleData数组中的TestComponent更改为仅传递两个道具, idonClickHandler

{
   id: 1,
   name: "Product one",
   action: <TestComponent id={1} onClickHandler={this.onClickHandler} />
 }

并将App组件中的onClickHandler方法更改为:

onClickHandler(id, callback) {
   // make the api request, call 'callback' function when request is completed
    setTimeout(() => {
      callback();
    }, 3000);
}

演示

编辑 crazy-fire-fvlhm

或者,您可以在App组件中创建onClickHandler function 以返回Promise ,该 API 请求完成时已完成。 这样您就不必将回调 function 从TestComponent传递给App组件中的onClickHandler方法。

onClickHandler方法更改为:

onClickHandler(id) {
   return new Promise((resolve, reject) => {
     setTimeout(resolve, 3000);
   });
}

并将TestComponent更改为:

const TestComponent = ({ id, onClickHandler }) => {
  const [showProgress, setShowProgress] = useState(false);

  const toggleShowProgress = () => {
    setShowProgress(showProgress => !showProgress);
  };

  const handleClick = () => {
    setShowProgress(true);

    onClickHandler(id)
      .then(toggleShowProgress)
      .catch(error => {
        toggleShowProgress();
        // handle the error
      });
  };

  return (
    <div>
      {showProgress ? (
        <p>In Progress </p>
      ) : (
        <button onClick={handleClick}>click me</button>
      )}
    </div>
  );
};

演示

编辑实用-sinoussi-r92qj

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM