React Advanced London 2022前端技术

React 的奇怪知识

2022-11-14  本文已影响0人  吴摩西

可以修改使用 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')

  1. 组件未定义的问题,应该都能通过静态检查,例如 lint 发现。
  2. 支持 undefined,可以让某些组件的定义变得简单。
  3. 为了跟 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 还有 memoforwardRef

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 中。

Named Exports

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

总结

需要认真学习文档

上一篇下一篇

猜你喜欢

热点阅读