Есть ли способ сделать setState синхронным для решения проблемы рендеринга? - PullRequest
1 голос
/ 26 сентября 2019

Я столкнулся с проблемой.Я только что узнал, что setState является асинхронным.Я рендерил компонент в моем методе рендеринга, если определенное условие истинно.

Reder ():

render() {
        const { isFetchingSubject, isFetchingTemplate } = this.props;
        return (
            ...
                            {this.state.showLabelDetails && <Details template={this.props.match.params.templatename} close={this.toggleShowLabelDetails} data={this.state.labelDetails} />}
            ...
        );
    }

Вызов функции при нажатии кнопки:

toggleShowLabelDetails = (event) => {
        if (!this.state.showLabelDetails) this.setState({ labelDetails: JSON.parse(event.target.value) })
        this.setState({ showLabelDetails: !this.state.showLabelDetails });
        if (this.state.showLabelDetails) this.setState({ labelDetails: {} })
    }

состояние:

state = { 
        showLabelDetails: false,
        labelDetails: {},
     }

Объяснение того, что делает код:

  • Когда пользователь нажимает кнопку X, он вызывает функцию toggleShowLabelDetails ()
  • Itизменяет логическое значение в состоянии на true и добавляет значение из кнопки, состояние labelDetails, являющееся объектом.
  • Состояние изменяется, что означает, что компонент будет визуализироваться снова, а когда условие истинно, он будет отображатьсяновый компонент на экране.

50% времени он работает хорошо, но иногда я получаю следующую ошибку:

Uncaught SyntaxError: Unexpected token u in JSON at position 0
at Object.parse (<anonymous>)

Uncaught Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. 

Есть ли какое-либо решение для этого?

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

Вы можете передать обратный вызов в setState.

this.setState(
    (state, props) => ({showLabelDetails : !state.showLabelDetails}),
    () => { // Executed when state has been updated
        // Do stuff with new state
        if (this.state.showLabelDetails) {
            this.setState({ labelDetails: {} })
        }
    }
)

И кстати: вы не можете полагаться на this.state внутри setState (упомянуто в документах реагирования), так как реагирование может пакетно обновлять состояние.

1 голос
/ 26 сентября 2019

Можете ли вы попробовать сделать что-то вроде этого:

class MyComponent extends Component {

function setStateSynchronous(stateUpdate) {
    return new Promise(resolve => {
        this.setState(stateUpdate, () => resolve());
    });
}

async function foo() {
    // state.count has value of 0
    await setStateSynchronous(state => ({count: state.count+1}));
    // execution will only resume here once state has been applied
    console.log(this.state.count);  // output will be 1
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...