Loading...
Loading...
Compare original and translation side by side
useStateuseEffectuseuseEffectuseMemouseCallbackuseStateuseEffectuseuseEffectuseMemouseCallbackclass MyComponent extends React.Component {
/* Adding state and binding custom methods */
constructor() {
super()
this.state = { ... }
this.customMethodOne = this.customMethodOne.bind(this)
this.customMethodTwo = this.customMethodTwo.bind(this)
}
/* Lifecycle Methods */
componentDidMount() { ...}
componentWillUnmount() { ... }
/* Custom methods */
customMethodOne() { ... }
customMethodTwo() { ... }
render() { return { ... }}
}componentDidMountcomponentWillUnmountclass MyComponent extends React.Component {
/* 添加状态并绑定自定义方法 */
constructor() {
super()
this.state = { ... }
this.customMethodOne = this.customMethodOne.bind(this)
this.customMethodTwo = this.customMethodTwo.bind(this)
}
/* 生命周期方法 */
componentDidMount() { ...}
componentWillUnmount() { ... }
/* 自定义方法 */
customMethodOne() { ... }
customMethodTwo() { ... }
render() { return { ... }}
}componentDidMountcomponentWillUnmountdivfunction Button() {
return <div className="btn">disabled</div>;
}disabledenabledenableddisabledexport default class Button extends React.Component {
constructor() {
super();
this.state = { enabled: false };
}
render() {
const { enabled } = this.state;
const btnText = enabled ? "enabled" : "disabled";
return (
<div
className={`btn enabled-${enabled}`}
onClick={() => this.setState({ enabled: !enabled })}
>
{btnText}
</div>
);
}
}bindconstructorthisdivfunction Button() {
return <div className="btn">disabled</div>;
}disabledenabledenableddisabledexport default class Button extends React.Component {
constructor() {
super();
this.state = { enabled: false };
}
render() {
const { enabled } = this.state;
const btnText = enabled ? "enabled" : "disabled";
return (
<div
className={`btn enabled-${enabled}`}
onClick={() => this.setState({ enabled: !enabled })}
>
{btnText}
</div>
);
}
}this<WrapperOne>
<WrapperTwo>
<WrapperThree>
<WrapperFour>
<WrapperFive>
<Component>
<h1>Finally in the component!</h1>
</Component>
</WrapperFive>
</WrapperFour>
</WrapperThree>
</WrapperTwo>
</WrapperOne><WrapperOne>
<WrapperTwo>
<WrapperThree>
<WrapperFour>
<WrapperFive>
<Component>
<h1>终于到目标组件了!</h1>
</Component>
</WrapperFive>
</WrapperFour>
</WrapperThree>
</WrapperTwo>
</WrapperOne>counterwidthcomponentDidMountcomponentWillUnmountresizecounterwidthcomponentDidMountcomponentWillUnmountresizecomponentDidMountcomponentWillUnmountcomponentDidMountcomponentWillUnmountuseStateuseStateInputinputclass Input extends React.Component {
constructor() {
super();
this.state = { input: "" };
this.handleInput = this.handleInput.bind(this);
}
handleInput(e) {
this.setState({ input: e.target.value });
}
render() {
<input onChange={handleInput} value={this.state.input} />;
}
}useStateuseStateuseStateuseStateconst [value, setValue] = React.useState(initialValue);this.state.[value]this.setStateinputsetInputconst [input, setInput] = React.useState("");Inputfunction Input() {
const [input, setInput] = React.useState("");
return <input onChange={(e) => setInput(e.target.value)} value={input} />;
}inputinputinputsetInputuseStateuseStateInputinputclass Input extends React.Component {
constructor() {
super();
this.state = { input: "" };
this.handleInput = this.handleInput.bind(this);
}
handleInput(e) {
this.setState({ input: e.target.value });
}
render() {
<input onChange={handleInput} value={this.state.input} />;
}
}useStateuseStateuseStateuseStateconst [value, setValue] = React.useState(initialValue);this.state.[value]this.setStateinputsetInputconst [input, setInput] = React.useState("");Inputfunction Input() {
const [input, setInput] = React.useState("");
return <input onChange={(e) => setInput(e.target.value)} value={input} />;
}inputinputsetInputuseStateuseEffectuseEffectcomponentDidMountcomponentDidUpdatecomponentWillUnmountcomponentDidMount() { ... }
useEffect(() => { ... }, [])
componentWillUnmount() { ... }
useEffect(() => { return () => { ... } }, [])
componentDidUpdate() { ... }
useEffect(() => { ... })useEffectinputinputuseEffectuseEffectuseEffect(() => {
console.log(`The user typed ${input}`);
}, [input]);useStateuseEffectuseEffectcomponentDidMountcomponentDidUpdatecomponentWillUnmountcomponentDidMount() { ... }
useEffect(() => { ... }, [])
componentWillUnmount() { ... }
useEffect(() => { return () => { ... } }, [])
componentDidUpdate() { ... }
useEffect(() => { ... })inputuseEffectinputuseEffectuseEffectuseEffect(() => {
console.log(`The user typed ${input}`);
}, [input]);useStateuseEffectuseReduceruseRefuseContextuseMemouseImperativeHandleuseLayoutEffectuseDebugValueuseCallbackuseusefunction useKeyPress(targetKey) {
const [keyPressed, setKeyPressed] = React.useState(false);
function handleDown({ key }) {
if (key === targetKey) {
setKeyPressed(true);
}
}
function handleUp({ key }) {
if (key === targetKey) {
setKeyPressed(false);
}
}
React.useEffect(() => {
window.addEventListener("keydown", handleDown);
window.addEventListener("keyup", handleUp);
return () => {
window.removeEventListener("keydown", handleDown);
window.removeEventListener("keyup", handleUp);
};
}, []);
return keyPressed;
}InputuseKeyPressAppuseCountercountincrementdecrementuseWindowWidthAppCounterWidthuseStateuseEffectuseReduceruseRefuseContextuseMemouseImperativeHandleuseLayoutEffectuseDebugValueuseCallbackfunction useKeyPress(targetKey) {
const [keyPressed, setKeyPressed] = React.useState(false);
function handleDown({ key }) {
if (key === targetKey) {
setKeyPressed(true);
}
}
function handleUp({ key }) {
if (key === targetKey) {
setKeyPressed(false);
}
}
React.useEffect(() => {
window.addEventListener("keydown", handleDown);
window.addEventListener("keyup", handleUp);
return () => {
window.removeEventListener("keydown", handleDown);
window.removeEventListener("keyup", handleUp);
};
}, []);
return keyPressed;
}useKeyPressInputAppuseCountercountincrementdecrementuseWindowWidthAppCounterWidthuseStateuseStateuseStateuseStateuseEffectuseEffectuseEffectcomponentDidMountcomponentDidUpdatecomponentWillUnmountuseEffectuseEffectcomponentDidMountcomponentDidUpdatecomponentWillUnmountuseContextuseContextuseContextReact.createContextuseContextuseContextuseContextReact.createContextuseContextuseContextuseContextuseReduceruseReduceruseReducersetStatereducerdispatchuseReduceruseReducersetStatereducerdispatchuseReduceruseStateclass TweetSearchResults extends React.Component {
constructor(props) {
super(props);
this.state = {
filterText: "",
inThisLocation: false,
};
this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
this.handleInThisLocationChange =
this.handleInThisLocationChange.bind(this);
}
handleFilterTextChange(filterText) {
this.setState({
filterText: filterText,
});
}
handleInThisLocationChange(inThisLocation) {
this.setState({
inThisLocation: inThisLocation,
});
}
render() {
return (
<div>
<SearchBar
filterText={this.state.filterText}
inThisLocation={this.state.inThisLocation}
onFilterTextChange={this.handleFilterTextChange}
onInThisLocationChange={this.handleInThisLocationChange}
/>
<TweetList
tweets={this.props.tweets}
filterText={this.state.filterText}
inThisLocation={this.state.inThisLocation}
/>
</div>
);
}
}const TweetSearchResults = ({ tweets }) => {
const [filterText, setFilterText] = useState("");
const [inThisLocation, setInThisLocation] = useState(false);
return (
<div>
<SearchBar
filterText={filterText}
inThisLocation={inThisLocation}
setFilterText={setFilterText}
setInThisLocation={setInThisLocation}
/>
<TweetList
tweets={tweets}
filterText={filterText}
inThisLocation={inThisLocation}
/>
</div>
);
};class TweetSearchResults extends React.Component {
constructor(props) {
super(props);
this.state = {
filterText: "",
inThisLocation: false,
};
this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
this.handleInThisLocationChange =
this.handleInThisLocationChange.bind(this);
}
handleFilterTextChange(filterText) {
this.setState({
filterText: filterText,
});
}
handleInThisLocationChange(inThisLocation) {
this.setState({
inThisLocation: inThisLocation,
});
}
render() {
return (
<div>
<SearchBar
filterText={this.state.filterText}
inThisLocation={this.state.inThisLocation}
onFilterTextChange={this.handleFilterTextChange}
onInThisLocationChange={this.handleInThisLocationChange}
/>
<TweetList
tweets={this.props.tweets}
filterText={this.state.filterText}
inThisLocation={this.state.inThisLocation}
/>
</div>
);
}
}const TweetSearchResults = ({ tweets }) => {
const [filterText, setFilterText] = useState("");
const [inThisLocation, setInThisLocation] = useState(false);
return (
<div>
<SearchBar
filterText={filterText}
inThisLocation={inThisLocation}
setFilterText={setFilterText}
setInThisLocation={setInThisLocation}
/>
<TweetList
tweets={tweets}
filterText={filterText}
inThisLocation={inThisLocation}
/>
</div>
);
};Note (React 18+): Avoiding Unnecessary EffectsModern best practices refine how we use effects and event handlers. It's easy to overuse— the new React docs caution: "If there is no external system involved, you shouldn't need an Effect. Removing unnecessary Effects will make your code easier to follow, faster to run, and less error-prone." (react.dev)useEffectInstead of using an effect to set derived state (e.g.,), compute it directly in the component body:useEffect(() => setFullName(firstName + ' ' + lastName), [firstName, lastName]). Similarly, handle user events like form submission or logging directly in event handlers rather than in effects. This reduces double renders and "stale closure" bugs.const fullName = firstName + ' ' + lastNameAutomatic Memoization via React Compiler: New in React 19 is the React Optimizing Compiler (sometimes called React Forget) which can handle manyanduseCallbackoptimizations for you. When enabled, the compiler statically analyzes your component code and automatically hoists stable functions and memoizes values that don't need to change. The official React docs note that the compiler "handles memoization for you, eliminating the need for manual useMemo, useCallback, and React.memo" in many cases. Writing clean functional components (no side-effects in render, pure computations) will allow the compiler to maximize optimizations.useMemo
useEffectuseCallbackuseMemo注意(React 18+):避免不必要的副作用现代最佳实践优化了我们使用副作用和事件处理程序的方式。很容易过度使用——新的React文档警告:“如果不涉及外部系统,你应该不需要使用副作用。移除不必要的副作用会让你的代码更易于理解、运行更快且更不易出错。”(react.dev)useEffect不要使用副作用来设置派生状态(例如),而是直接在组件主体中计算:useEffect(() => setFullName(firstName + ' ' + lastName), [firstName, lastName])。同样,直接在事件处理程序中处理表单提交或日志记录等用户事件,而非在副作用中处理。这减少了重复渲染和“过时闭包”错误。const fullName = firstName + ' ' + lastName通过React Compiler实现自动记忆化:React 19中的新特性是React优化编译器(有时称为React Forget),它可以为你处理许多和useCallback优化。启用后,编译器会静态分析你的组件代码,并自动提升稳定函数并记忆不需要更改的值。官方React文档指出,编译器“为你处理记忆化,在许多情况下消除了手动使用useMemo、useMemo和useCallback的需求”。编写简洁的函数式组件(渲染时无副作用、纯计算)将使编译器最大化优化效果。React.memo
| React Hooks | Classes |
|---|---|
| It helps avoid multiple hierarchies and make code clearer | Generally, when you use HOC or renderProps, you have to restructure your App with multiple hierarchies when you try to see it in DevTools |
| It provides uniformity across React components. | Classes confuse both humans and machines due to the need to understand binding and the context in which functions are called. |
| React Hooks | 类组件 |
|---|---|
| 避免多层嵌套,让代码更清晰 | 通常,当你使用HOC或渲染属性时,在开发者工具中查看应用时,你会发现应用被重构为多层嵌套结构 |
| 在React组件之间提供一致性 | 类组件会让人类和机器都感到困惑,因为需要理解绑定以及函数调用的上下文 |