在 React class 中设置等待设置状态可以吗?
Is this okay to set await on set state in react class?
嗨,我是 React 的新手,我正在实施 react-table
。我知道如果任何道具发生变化,反应会自动渲染组件。现在,为了我的工作 table,我正在尝试根据复选框在列上隐藏和显示过滤器。 react-table
已经提供了 filterable
选项来执行此操作。但我不想在我的 actions
列中显示过滤器。
这里
class JobsTable extends React.Component {
constructor() {
super();
this.state = {
data: [],
isFilterable: true,
};
}
componentDidMount() {
this.getJobs();
}
getFormattedDate(dateString) {
const current_datetime = new Date(dateString);
const formatted_date =
('0' + current_datetime.getDate()).slice(-2) +
'/' +
('0' + (current_datetime.getMonth() + 1)).slice(-2) +
'/' +
current_datetime.getFullYear();
return formatted_date;
}
getJobs = async pageIndex => {
pageIndex = pageIndex || 1;
this.setState({ isLoading: true });
const { recordsToFetch } = this.state;
const resp = await getAllJobs(pageIndex, recordsToFetch);
if (resp.success) {
this.setState({
data: resp.data.jobs,
pages: Math.ceil(resp.data.totalRecords / recordsToFetch),
isLoading: false,
showPagination: resp.data.jobs.length > 0,
});
} else {
this.setState({ data: [], isLoading: false, showPagination: false });
}
ReactTooltip.rebuild();
};
getCell(row) {
let value = row.value !== undefined && row.value !== null ? row.value : '';
if (row.column.Header === 'Submitted') {
value = this.getFormattedDate(value);
}
if (row.column.Header === 'Problem Summary') {
value = Array.isArray(value) ? value.join('. ') : value;
}
if (row.column.Header === 'Quotes') {
value = JSON.stringify(value);
}
if (row.column.Header === 'Actions') {
return (
<>
<div
id="view"
className="react-table-cell-style"
style={{ display: 'inline', cursor: 'pointer' }}>
{' '}
<a
rel="noopener noreferrer"
target="_blank"
href={`/job/${row.original.userId}/${row.original.jobId}`}>
View
</a>
</div>{' '}
<div
id="edit"
className="react-table-cell-style"
style={{ display: 'inline', cursor: 'pointer' }}>
| Edit
</div>{' '}
<div
id="viewQuote"
style={{ display: 'inline', cursor: 'pointer' }}
className="react-table-cell-style">
{value > 0 && `| Quote${value > 1 ? 's' : ''}`}
</div>
</>
);
}
return (
<div data-tip={row.column.Header + ' : ' + value} className="react-table-cell-style">
<span>{value}</span>
</div>
);
}
getHeader(headerName, valueAccessor, sortable = true) {
const { isFilterable } = this.state;
const headerClassName = 'react-table-header';
return {
headerClassName: headerClassName,
Header: headerName,
accessor: valueAccessor,
Cell: row => this.getCell(row),
filterable: headerName === 'Actions' ? false : isFilterable,
sortable: sortable,
width: headerName === 'Actions' ? 140 : undefined,
};
}
render() {
let jobColumns = [
this.getHeader('Job ID', 'jobId'),
this.getHeader('User ID', 'userId'),
this.getHeader('Name', 'name'),
this.getHeader('Email', 'email'),
this.getHeader('Submitted', 'submitted'),
this.getHeader('Status', 'status'),
this.getHeader('Phone Number', 'number'),
this.getHeader('Device', 'device'),
this.getHeader('Make', 'make'),
this.getHeader('Model', 'model'),
this.getHeader('Problem Summary', 'problemSummary'),
this.getHeader('Anything else?', 'anythingElse'),
this.getHeader('Postcode', 'postcode'),
this.getHeader("T's Matched", 'techspertMatchedCount'),
this.getHeader('Not Available', 'techspertNotAvailable'),
this.getHeader('Quotes', 'quotesCount'),
this.getHeader('Viewed Quote', 'viewedQuote'),
this.getHeader('Chatted with T', 'isChatted'),
this.getHeader('Got to Payment', 'gotToPayment'),
this.getHeader('Actions', 'quotesCount', false),
];
const {
data,
isFilterable,
} = this.state;
const setFilters = async () => {
const { isFilterable } = this.state;
await this.setState({ isFilterable: !isFilterable });
this.getJobs();
};
return (
<div className="jobsTable-Container">
<div className="jobsTable_show-filter">
<input
type="checkbox"
onChange={setFilters}
checked={isFilterable}
value={isFilterable}
/>
Show Filters
</div>
<ReactTable
data={data}
columns={jobColumns}
filterable
/>
</div>
);
}
}
export default JobsTable;
我想提出的问题是,在setFilters
方法中使用await
是否可以。因为如果我不这样做并调用 getJobs
方法,旧值不会更新。这样可以吗?
这里的主要问题是 getJobs
依赖于状态是最新的,但是由于状态更新是异步的,更新发生在 [=14] 之后=] 打电话。通过添加 await
,您将 getJobs
调用推迟到微任务。这可能(也可能不是!)在状态更新之后:
------------- time ---------->
setState -------> state update
await --------> getJobs
所以你的"fix"有问题。而是使用 setState
的第二个参数,它在状态更新后明确调用:
this.setState({ isFilterable: !isFilterable }, () => this.getJobs());
或者更好,不依赖于当前状态:
this.setState(({ isFilterable }) => ({ isFilterable: !isFilterable }), () => this.getJobs());
将上图变为:
setState -> state update -> getJobs
您不应该将 await 与 setState 结合使用,我想您正在寻找的应该是这样的。
this.setState({
isFilterable: !isFilterable
}, () => {
this.getJobs()
});
嗨,我是 React 的新手,我正在实施 react-table
。我知道如果任何道具发生变化,反应会自动渲染组件。现在,为了我的工作 table,我正在尝试根据复选框在列上隐藏和显示过滤器。 react-table
已经提供了 filterable
选项来执行此操作。但我不想在我的 actions
列中显示过滤器。
这里
class JobsTable extends React.Component {
constructor() {
super();
this.state = {
data: [],
isFilterable: true,
};
}
componentDidMount() {
this.getJobs();
}
getFormattedDate(dateString) {
const current_datetime = new Date(dateString);
const formatted_date =
('0' + current_datetime.getDate()).slice(-2) +
'/' +
('0' + (current_datetime.getMonth() + 1)).slice(-2) +
'/' +
current_datetime.getFullYear();
return formatted_date;
}
getJobs = async pageIndex => {
pageIndex = pageIndex || 1;
this.setState({ isLoading: true });
const { recordsToFetch } = this.state;
const resp = await getAllJobs(pageIndex, recordsToFetch);
if (resp.success) {
this.setState({
data: resp.data.jobs,
pages: Math.ceil(resp.data.totalRecords / recordsToFetch),
isLoading: false,
showPagination: resp.data.jobs.length > 0,
});
} else {
this.setState({ data: [], isLoading: false, showPagination: false });
}
ReactTooltip.rebuild();
};
getCell(row) {
let value = row.value !== undefined && row.value !== null ? row.value : '';
if (row.column.Header === 'Submitted') {
value = this.getFormattedDate(value);
}
if (row.column.Header === 'Problem Summary') {
value = Array.isArray(value) ? value.join('. ') : value;
}
if (row.column.Header === 'Quotes') {
value = JSON.stringify(value);
}
if (row.column.Header === 'Actions') {
return (
<>
<div
id="view"
className="react-table-cell-style"
style={{ display: 'inline', cursor: 'pointer' }}>
{' '}
<a
rel="noopener noreferrer"
target="_blank"
href={`/job/${row.original.userId}/${row.original.jobId}`}>
View
</a>
</div>{' '}
<div
id="edit"
className="react-table-cell-style"
style={{ display: 'inline', cursor: 'pointer' }}>
| Edit
</div>{' '}
<div
id="viewQuote"
style={{ display: 'inline', cursor: 'pointer' }}
className="react-table-cell-style">
{value > 0 && `| Quote${value > 1 ? 's' : ''}`}
</div>
</>
);
}
return (
<div data-tip={row.column.Header + ' : ' + value} className="react-table-cell-style">
<span>{value}</span>
</div>
);
}
getHeader(headerName, valueAccessor, sortable = true) {
const { isFilterable } = this.state;
const headerClassName = 'react-table-header';
return {
headerClassName: headerClassName,
Header: headerName,
accessor: valueAccessor,
Cell: row => this.getCell(row),
filterable: headerName === 'Actions' ? false : isFilterable,
sortable: sortable,
width: headerName === 'Actions' ? 140 : undefined,
};
}
render() {
let jobColumns = [
this.getHeader('Job ID', 'jobId'),
this.getHeader('User ID', 'userId'),
this.getHeader('Name', 'name'),
this.getHeader('Email', 'email'),
this.getHeader('Submitted', 'submitted'),
this.getHeader('Status', 'status'),
this.getHeader('Phone Number', 'number'),
this.getHeader('Device', 'device'),
this.getHeader('Make', 'make'),
this.getHeader('Model', 'model'),
this.getHeader('Problem Summary', 'problemSummary'),
this.getHeader('Anything else?', 'anythingElse'),
this.getHeader('Postcode', 'postcode'),
this.getHeader("T's Matched", 'techspertMatchedCount'),
this.getHeader('Not Available', 'techspertNotAvailable'),
this.getHeader('Quotes', 'quotesCount'),
this.getHeader('Viewed Quote', 'viewedQuote'),
this.getHeader('Chatted with T', 'isChatted'),
this.getHeader('Got to Payment', 'gotToPayment'),
this.getHeader('Actions', 'quotesCount', false),
];
const {
data,
isFilterable,
} = this.state;
const setFilters = async () => {
const { isFilterable } = this.state;
await this.setState({ isFilterable: !isFilterable });
this.getJobs();
};
return (
<div className="jobsTable-Container">
<div className="jobsTable_show-filter">
<input
type="checkbox"
onChange={setFilters}
checked={isFilterable}
value={isFilterable}
/>
Show Filters
</div>
<ReactTable
data={data}
columns={jobColumns}
filterable
/>
</div>
);
}
}
export default JobsTable;
我想提出的问题是,在setFilters
方法中使用await
是否可以。因为如果我不这样做并调用 getJobs
方法,旧值不会更新。这样可以吗?
这里的主要问题是 getJobs
依赖于状态是最新的,但是由于状态更新是异步的,更新发生在 [=14] 之后=] 打电话。通过添加 await
,您将 getJobs
调用推迟到微任务。这可能(也可能不是!)在状态更新之后:
------------- time ---------->
setState -------> state update
await --------> getJobs
所以你的"fix"有问题。而是使用 setState
的第二个参数,它在状态更新后明确调用:
this.setState({ isFilterable: !isFilterable }, () => this.getJobs());
或者更好,不依赖于当前状态:
this.setState(({ isFilterable }) => ({ isFilterable: !isFilterable }), () => this.getJobs());
将上图变为:
setState -> state update -> getJobs
您不应该将 await 与 setState 结合使用,我想您正在寻找的应该是这样的。
this.setState({
isFilterable: !isFilterable
}, () => {
this.getJobs()
});