#reactjs #react-redux #material-ui #react-state #react-state-management
#reactjs #реагирует-redux #материал-пользовательский интерфейс #реагирует на состояние #реагирует-управление состоянием
Вопрос:
Поэтому я намерен каждый раз, когда я нажимаю стрелку следующей страницы, состояние обновляет номер страницы и вызывает getData() для получения данных из удаленной базы данных, а затем обновляет work_orders в состоянии. Но проблема в том, что состояние обновляется не сразу: оно всегда на один шаг позади. Я перепробовал множество решений из поиска в Google, но ничего не работает. Интересно, знает ли кто-нибудь, как решить эту проблему? может ли redux или hooks решить эту проблему?
Спасибо.
p.s: извините, код выглядит немного запутанным, я перепробовал слишком много вещей.
export default class TableList extends React.Component {
state = {
work_orders:[],
// search : "",
URL : 'http://localhost:8000/api/',
query: {
paginate : {
page: 1,
pageSize: 20,
totalPage: 0,
totalRows: 0,
startIndex: 0,
endIndex: 0,
},
condition: [],
sorting: {
id: 0,
order: "ASC",
},
search: "",
columns: [
{ title: 'WOID', field: 'WOID', type: 'numeric'},
{ title: 'Quantity', field: 'quantity', type: 'numeric'},
{ title: 'Order Status', field: 'orderStatus', },
{ title: 'Start Date', field: 'startDate', },
{title: 'End Date', field: 'endDate', }],
},
}
handleSearchChange =(text)=>{
this.setState(prevState=>({
query:{
...prevState.query,
search: text,
}
}));
console.log('query search is' this.state.query.search);
this.getData();
}
componentDidMount(prevProps, prevState, snapshot){
console.log("did mount");
this.getData();
}
// static getDerivedStateFromProps(){
// this.getData();
// }
getData=()=>{
console.log('IN getDate');
var url = this.state.URL 'test?'
var query = this.state.query;
console.log("page is: " this.state.query.paginate.page);
Axios.post( url, query).then(result=>{
console.log("page is: " this.state.query.paginate.page);
var pagi = result.data.pop();
console.log("pagi is " pagi.page);
this.setState(prevState=>({
query:{
...prevState.query,
paginate:{
...prevState.query.paginate,
totalRows: pagi.totalRows,
totalPage: pagi.totalPage,
startIndex: pagi.startIndex,
endIndex: pagi.endIndex,
}
}}))
this.setState({work_orders: [...result.data]});
})}
componentDidUpdate(){
}
shouldComponentUpdate(){
return true;
}
handleFilterChange=(id_, val_)=>{
var fl = false;
if(this.state.query.condition.flag == false){
fl = true;
}
this.setState(prevState=>({
...prevState,
query:{
...prevState.query,
condition: [
...prevState.query.condition,
{id: id_, val: val_}
]
}
}
))
this.getData();
console.log(this.state);
// this.getData()
}
// componentDidUpdate(){
// this.getData();
// }
handleNextButtonClick= () =>{
console.log("in handle next");
this.setState((prevState, props)=>{
return{
...prevState,
query:{
...prevState.query,
paginate: {
...prevState.query.paginate,
page: prevState.query.paginate.page 1,
}
}
}
}
);
console.log('page is ' this.state.query.paginate.page);
this.getData();
}
handlePrevButtonClick=()=>{
this.setState(prevState=>({
...prevState,
query:{
...prevState.query,
paginate: {
...prevState.query.paginate,
page: prevState.query.paginate.page - 1,
}
}
}))
this.getData();
}
handleFirstButtonClick=()=>{
this.setState(prevState=>({
...prevState,
query:{
...prevState.query,
paginate: {
...prevState.query.paginate,
page: 1,
startIndex: 0,
endIndex: prevState.query.paginate.pageSize
}
}
}))
this.getData();
}
handleLastButtonClick=()=>{
this.setState(prevState=>({
...prevState,
query:{
...prevState.query,
paginate: {
...prevState.query.paginate,
page: prevState.query.paginate.totalPage,
}
}
}))
this.getData();
}
render(){
console.log(this.state.work_orders);
return (
<div>
<MaterialTable
options={{
sorting: true,
filtering: false,
search: true,
exportButton: true,
pageSize: 20,
pageSizeOptions: [5, 20, 50, 100],
thirdSortClick: true,
initialPage: 0,
debounceInterval: 500,
paging: true,
}}
// data = {this.state.work_orders}
columns={this.state.query.columns}
data={this.state.work_orders}
title="Work Orders"
components={{
Toolbar: props => (<MTableToolbar
{...props}
ref={ref => (this.child = ref)}
setState={state => this.setState(state)}
onSearchChanged={debounce((searchtext) => {
console.log('the text is: ' searchtext);
// const query = {...this.child.state.query}
// this.child.setState({searchText: text});
this.handleSearchChange(searchtext);
}, 500)}
/>),
Pagination: props => (<CustomPagination
{...props}
rowsPerPage = {this.state.query.paginate.pageSize}
pageIndex = {this.state.query.paginate.page}
count = {this.state.query.paginate.totalPage}
rows={this.state.query.paginate.totalRows}
startIndex={this.state.query.paginate.startIndex}
endIndex={this.state.query.paginate.endIndex}
handleNextButtonClick={this.handleNextButtonClick}
handlePrevButtonClick={this.handlePrevButtonClick}
handleFirstButtonClick={this.handleFirstButtonClick}
handleLastButtonClick={this.handleLastButtonClick}
/>)
}}
/>
</div>
);
}
}
<!-- begin snippet: js hide: false console: true babel: false -->
function CustomPagination (props){
const handleNextButtonClick=()=>{
props.handleNextButtonClick();
}
const handlePrevButtonClick=()=>{
props.handlePrevButtonClick();
}
const handleFirstButtonClick=()=>{
props.handleFirstButtonClick();
}
const handleLastButtonClick=()=>{
props.handleLastButtonClick();
}
return(
<div style={{
display: 'grid',
paddingTop: '10px',
gridTemplateColumns: '15% 25% 20% 25% 15%'
}}>
<Tooltip title={'FirstPage'}>
<span >
<IconButton color="primary" onClick={handleFirstButtonClick} style={{float: 'left'}} >
<FirstPageIcon fontSize="large" />
</IconButton>
</span>
</Tooltip>
<Tooltip title={'PrevPage'} >
<span>
<IconButton color="primary" onClick={handlePrevButtonClick} style={{float: 'left'}} >
<NavigateBeforeIcon fontSize="large" />
</IconButton>
</span>
</Tooltip>
<span>
<p style={{
paddingBottom: '5px',
paddingTop: '5px',
marginBottom: '0',
marginTop: '0',
// backgroundColor: 'blue',
textAlign: 'center',
}}>{props.startIndex} to {props.endIndex} from {props.rows}
</p>
</span>
<Tooltip title={'NextPage'}>
<span>
<IconButton color="primary" style={{float: 'right'}} onClick={handleNextButtonClick}>
<NavigateNextIcon fontSize="large" />
</IconButton>
</span>
</Tooltip>
<Tooltip title={'LastPage'} >
<span>
<IconButton color="primary" style={{float: 'right'}} onClick={handleLastButtonClick}>
<LastPageIcon fontSize="large" />
</IconButton>
</span>
</Tooltip>
</div>
);
}
export default CustomPagination;
Комментарии:
1. Вам нужно будет предоставить подробную информацию о том, как вы управляете своим состоянием. Вот где будет проблема. С другой стороны, вы, вероятно, можете вызывать функции из реквизитов напрямую, вместо того, чтобы переносить их сюда.
2. извините, я забыл скопировать родительский компонент.
Ответ №1:
Проблема в том, что изменение состояния будет происходить асинхронно после выполнения текущей функции. Возможным решением является использование функции обратного вызова в качестве второго аргумента setState, которая вызывает обратный вызов после изменения состояния:
handleSearchChange = (text) => {
this.setState(
prevState => ({
...prevState,
query:{
...prevState.query,
search: text,
}
}),
() => {
console.log('query search is' this.state.query.search);
this.getData();
}
);
}
Комментарии:
1. Спасибо за ваш щедрый ответ, это сработало!!!! Я знаю, что это может быть неправильным способом реализации такого компонента. Каков правильный способ реализовать это? вместо этого использовать функцию и реагировать на хук?
2. Классы @Chase по-прежнему удобны в использовании. Рекомендуется в какой-то момент изучить api hooks для будущих функций react.