如何更改作为列传递给 React Table 的子组件的道具的值?
How to change the value of a prop of Sub Component passed as a column to React Table?
我在 Web 应用程序中使用 React Table 库。
我将一个组件作为列传递给 table。 table 的列和数据如下所示。
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
它应该传递给 table 并且需要文本为进行中,直到 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 为我提供更好的解决方案。谢谢
而不是将 inProgress
属性传递给 TestComponent
,您可以在 TestComponent
中维护一个本地状态,用于确定是否显示进度文本或按钮,并且只传递id
和 onClickHanlder
道具 TestComponent
.
在TestComponent
中点击按钮时,可以设置TestComponent
的本地状态显示进度文本,然后调用作为prop传递的onClickHandler
函数,传入id
属性和回调函数作为参数。当 API 请求完成时将调用此回调函数。此回调函数在 TestComponent
内定义,仅切换 TestComponent
的本地状态以隐藏进度文本并再次显示按钮。
将您的 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
的本地状态,因为它是一个功能组件,但您也可以在 class 组件中使用相同的逻辑。
将 sampleData
数组中的 TestComponent
更改为仅传递两个属性,id
和 onClickHandler
。
{
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);
}
演示
或者,您可以使 App
组件中的 onClickHandler
函数成为 return 一个 Promise
,当 API 请求完成时,它会被执行。这样您就不必将回调函数从 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>
);
};
演示
我在 Web 应用程序中使用 React Table 库。
我将一个组件作为列传递给 table。 table 的列和数据如下所示。
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
它应该传递给 table 并且需要文本为进行中,直到 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 为我提供更好的解决方案。谢谢
而不是将 inProgress
属性传递给 TestComponent
,您可以在 TestComponent
中维护一个本地状态,用于确定是否显示进度文本或按钮,并且只传递id
和 onClickHanlder
道具 TestComponent
.
在TestComponent
中点击按钮时,可以设置TestComponent
的本地状态显示进度文本,然后调用作为prop传递的onClickHandler
函数,传入id
属性和回调函数作为参数。当 API 请求完成时将调用此回调函数。此回调函数在 TestComponent
内定义,仅切换 TestComponent
的本地状态以隐藏进度文本并再次显示按钮。
将您的 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
的本地状态,因为它是一个功能组件,但您也可以在 class 组件中使用相同的逻辑。
将 sampleData
数组中的 TestComponent
更改为仅传递两个属性,id
和 onClickHandler
。
{
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);
}
演示
或者,您可以使 App
组件中的 onClickHandler
函数成为 return 一个 Promise
,当 API 请求完成时,它会被执行。这样您就不必将回调函数从 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>
);
};