异步碎片化状态更新
异步碎片化状态更新
Suspense
Here’s how suspending works:
- in the render method, read a value from the cache.
- if the value is already cached, the render continues like normal
- if the value is not already cached, the cache throws a promise
- when the promise resolves, React retries where it left off
const imageFetcher = createFetcher(src => {
new Promise(resolve => {
const image = new Image();
image.onload = () => {
resolve(src);
};
image.src = src;
});
});
function Img(props) {
return <img {...props} src={imageFetcher.read(prop.src)} />;
}
部分更新
import "./App.css";
import "antd/dist/antd.css";
import { Progress } from "antd";
import * as React from "react";
class App extends React.Component {
state = {
percent: 0,
isVisible: false
};
changePercent = () => {
this.setState({ isVisible: true }, () => {
let intVal = setInterval(() => {
if (this.state.percent < 100) {
let percent = this.state.percent + 1;
this.setState({ percent });
}
if (this.state.percent === 100) {
clearInterval(intVal);
this.setState({ isVisible: false, percent: 0 });
}
}, 10);
});
};
render() {
return (
<div>
<Progress
className={this.state.isVisible ? "" : "hidden"}
percent={this.state.percent}
strokeWidth={5}
showInfo={false}
/>
<progress max="100" value={this.state.percent} />
<button
onClick={() => {
this.changePercent();
}}
>
点我开始变化
</button>
</div>
);
}
}
export default App;
import React from "react";
import { render } from "react-dom";
// with fiber, we'll be able to write components that update text deep
// inside another string without wrapper dom, or rerendering the whole component
// before
class Lorem extends React.Component {
state = {
str: ""
};
onChange = e => {
this.setState({ str: e.target.value });
};
render() {
return (
<div>
<input onChange={this.onChange} />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt {this.state.str} ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore{" "}
{this.state.str} eu fugiat nulla pariatur. Excepteur sint occaecat{" "}
{this.state.str} cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</p>
</div>
);
}
}
// after
class Ipsum extends React.Component {
listeners = [];
listen = fn => {
this.listeners.push(fn);
};
unlisten = fn => {
this.listeners = this.listeners.filter(x => x !== fn);
};
onChange = e => {
this.listeners.forEach(x => x(e));
};
render() {
return (
<div>
<input onChange={this.onChange} />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt <Chunk listen={this.listen} /> ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore <Chunk listen={this.listen} /> eu fugiat nulla pariatur.
Excepteur sint occaecat
<Chunk listen={this.listen} /> cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</p>
</div>
);
}
}
// The secret sauce here is that components can now return strings
class Chunk extends React.Component {
state = {
str: this.props.initial || ""
};
componentDidMount() {
this.props.listen(e => this.setState({ str: e.target.value }));
}
render() {
return this.state.str;
}
}
// render(<Lorem/>, window.root)
render(<Ipsum />, window.root);