【问题标题】:Is there a way to make setState synchronous to solve render issue?有没有办法让 setState 同步来解决渲染问题?
【发布时间】:2019-09-26 10:27:58
【问题描述】:

我遇到了一个问题。我刚刚发现 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} />}
            ...
        );
    }

onclick 按钮上的函数调用:

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()
  • 它将状态中的布尔值更改为 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. 

有什么解决办法吗?

【问题讨论】:

  • 你打算用这个 sn-p {this.state.showLabelDetails &&
    }
  • 为什么点击时解析X标签中的值?
  • 跨域错误与反应渲染无关。大多数情况下,您可能在 Details 组件中尝试从 REST API 获取数据。如果 REST API 不支持或 Rest API 无法处理请求,您将收到跨域错误

标签: javascript reactjs state


【解决方案1】:

你可以尝试做这样的事情吗:

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
}

}

【讨论】:

  • 从技术上讲,这仍然是异步的。它只是从基于回调的转换为基于承诺的
【解决方案2】:

您可以将回调传递给 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: {} })
        }
    }
)

顺便说一句:你不能依赖 setState 中的 this.state(在 react 文档中提到),因为 react 可能会批量更新状态。

【讨论】:

  • 在你的例子中,我得到了以下编译错误:期望一个赋值或函数调用,而是看到一个表达式 no-unused-expressions
  • 对不起,距离我上次使用 React 已经有几个月了,现在修复它:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 2021-06-03
  • 1970-01-01
  • 2022-09-27
  • 2020-08-14
  • 1970-01-01
  • 2016-08-01
相关资源
最近更新 更多