gpt4 book ai didi

javascript - 在 React 中渲染 Promise

转载 作者:行者123 更新时间:2023-12-03 02:52:14 24 4
gpt4 key购买 nike

搜索这个问题总是会带来一些本质上可归结为的问题

class Test extends Component {
componentDidMount() {
this.props.promise.then(value => this.setState({value}));
}
render() {
return <div>{this.state.value || "Loading"}</div>;
}
}

如果 (1) 组件不会很快卸载,并且 (2) promise 永远不会改变,则此方法有效。当试图提出更通用的解决方案时,这两种情况都会产生潜在的问题。

第一个问题可以通过添加“guard”属性来解决,没什么大不了的。

当尝试解决第二个问题时,很容易遇到竞争条件。考虑以下代码:

const timedPromise = (value, delay) => new Promise((resolve, reject) => {
setTimeout(() => resolve(value), delay);
});

class Test extends React.Component {
constructor(props) {
super(props);
this.state = {value: "Loading..."};
}

componentWillMount() {
this.setPromise(timedPromise("Hello 1", 3000));
setTimeout(() => {
this.setPromise(timedPromise("Hello 2", 1000));
}, 1000);
}

setPromise(promise) {
promise.then(value => this.setState({value}));
}

render() {
return <div>{this.state.value}</div>;
}
}

ReactDOM.render(<Test/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

在此示例中,即使“Hello 2”请求稍后发起,但“Hello 1”将最终显示。这是某些界面中非常常见的问题,用户发出多个请求并最终得到不正确的状态。

我能想到的最佳解决方案如下:

const timedPromise = (value, delay) => new Promise((resolve, reject) => {
setTimeout(() => resolve(value), delay);
});

class Test extends React.Component {
constructor(props) {
super(props)
this.state = {data: {value: "Waiting..."}};
}

componentWillMount() {
this.setPromise(timedPromise("Hello 1", 3000));
setTimeout(() => {
this.setPromise(timedPromise("Hello 2", 1000));
}, 1000);
}

setPromise(promise) {
const data = {value: "Loading..."};
this.setState({data: data})
promise.then(value => {
data.value = value;
this.forceUpdate();
})
}

render() {
return <div>{this.state.data.value}</div>;
}
}

ReactDOM.render(<Test/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

这可行,但它依赖于forceUpdate,这看起来不太优雅。我似乎无法想出任何方法通过将一些值存储在不会遇到其他竞争条件的状态来解决这个问题,因为规范不保证 setState 分辨率的顺序。

是否有更好的模式来解决这个看似常见的问题?

最佳答案

您可以通过跟踪指针来解决此问题,并且仅在解析的指针与当前指针匹配(那么它是最新的)时才保存状态。否则忽略结果。

设置完毕后,这并不是在 React 中保持状态的最佳方式。毕竟它是一个 View 库。也许 Redux 可以帮助你(或者可能太多,这也是可能的,实际上取决于用例)。

如果你想将所有内容都保留在 React 中,你可以这样做。

class Example extends Component {
constructor(props) {
super(props);
this.state({value: 'Loading', currentPointer: 0});
}

componentDidMount() {
this.setPromise(timedPromise("Hello 1", 3000));
setTimeout(() => {
this.setPromise(timedPromise("Hello 2", 1000));
}, 1000);
}

setPromise(promise) {
const newPointer = this.state.currentPointer + 1;
this.setState({currentPointer: newPointer}, () =>
promise.then(value => {
if (this.state.currentPointer == newPointer) {
this.setState({value});
} else {
console.log(`Pointer mismatch, got ${newPointer} but current was ${this.state.currentPointer}`);
}
})
});
}

render() {
return <div>{this.state.data.value}</div>;
}
}

关于javascript - 在 React 中渲染 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47802597/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com