可以修改使用 key
props 重新加载 ( remount ) 组件
例如下面的代码,点击按钮,可以让 SomeComponent
重新加载
const App = () => {
const [id, setId] = useState('abc');
return (
<>
<SomeComponent key={id} />
<button onClick={() => setId(randomId())}>update</button>
</>
);
};
beta 版本的 react doc 帮助很多。值得一看。
避免 useEffect
的方法
flushSync
类似于 useLayoutEffect
,在 paint 之前修改状态,可以完成类似设置新信息并滚动过去的效果。
import { flushSync } from 'react-dom';
socket.onMessage((message) => {
flushSync(setMessages((preMessages) => {
...preMessages,
message
}));
scrollToLastMessage();
});
React 18 支持 Component 返回 undefined
以下的组件现在被认为是合法的:const App = () => undefined
。之前的版本不支持。原来这样的设定是为了避免某些组件没有定义,现在打开主要的原因是。(参考 React 18 allows components to render 'undefined')
- 组件未定义的问题,应该都能通过静态检查,例如 lint 发现。
- 支持 undefined,可以让某些组件的定义变得简单。
- 为了跟 Suspend 处理空 fallback 的行为一致
Composition 合成组件
mixins [已经不推荐了]
通过 mixins 实现双向绑定
var createReactClass = require('create-react-class');
var WithLink = createReactClass({
mixins: [LinkedStateMixin],
getInitialState: function() {
return {message: 'hello'};
},
render: function() {
return <input type="text" valueLink={this.linkState("message")} />;
}
});
通过 mixins 实现 Memo
var createReactClass = require('create-react-class');
var WithLink = createReactClass({
mixins: [PureRenderMixin],
render: function() {
return <div className={this.props.className} />;
}
});
High-order Components 高阶组件[大部分情况已经不推荐了]
// note that the order has resersed - props flow from top to bottom
const enhance = compose(
withState(/*...args*/),
mapProps(/*...args*/),
pure
)
const EnhancedComponent = enhance(BaseComponent);
使用高阶组件使得应用变得异常的复杂,难以维护。目前还遗存的 HOC 还有 memo
和 forwardRef
render props
render props 的嵌套让代码可读性变得很差。作者不得不装了 VSCode 的插件,让不同的括号显示不同的颜色
render() {
return (
<AsyncProps
activeItem={this.state.activeItem}
query={this.state.query}
data={this.state.data}
{
asyncProps => (
<AsyncBoundary>
{
isDetailLoading => (
<Debounce>
<MasterDetail
header={<Fragment>Header <button>click me</button></Fragment>}
search={<Fragment>Search <button>click me to Search</button></Fragment>}
/>
</Debounce>
)
}
</AsyncBoundary>
)
}
/>
);
}
Hooks
有状态的函数,不能应用在 class 中。
-
useContext
可以在 if 中调用,虽然 lint 不允许,但是可以 work。虽然不推荐使用。
Named Exports
- 使用带名字的 export 是更好的开发体验,帮助代码提示,帮助找到 export 的声明。
- React.lazy 默认只能支持 default export,不过通过实践,可以这么写
const MyComponent = lazy(() => (
import('./app').then(app => ({ default: app.MyComponent }))
));
TypeScript
最主要的问题是,有个隐藏的 children
props
type Props = {
message: sring;
}
// before React 18. don't use React.FC
// const Greeting: React.FC<Props> = (props) => {
const Greeting = (props: Props) => {
return <div>{props.message}</div>;
};
React 18 移除了这个隐藏的 children
props 传送门
type Props = {
title: sring;
children: React.ReactNode;
}
// Could use React.FC again, since the children is fixed.
const Greeting: React.FC<Props> = (props) => {
return (
<>
<h2>{props.title}</h2>
{props.children}
</>
);
};
// will result an error, if no children
<Greeting title="oh no" />
// only could use with children
<Greeting title="oh no">John</Greeting>
codemod 可以帮助进行代码升级。不过会被挂上 PropsWithChildren
npx types-react-codemod preset-18 ./src
useEffect
useEffect(() => {
const subscription = Keyboard.addListener('keyboardWillShow', () => {
setIsEditorBottomBarVisible(true);
});
return () => subscription.remove();
}, []);
Warnings
Can't perform a React state update on an unmount component.
问题在于,Warning 的提示信息太长了。没有办法正常的 debug。
React.StrictMode
会双重渲染,帮助发现有问题的 effect , hook 等。
SMDS Strick Mode Detection System
总结
需要认真学习文档
网友评论