Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hooks学习记录 - 可能被删 #57

Open
Genluo opened this issue Sep 6, 2019 · 5 comments
Open

hooks学习记录 - 可能被删 #57

Genluo opened this issue Sep 6, 2019 · 5 comments

Comments

@Genluo
Copy link
Owner

Genluo commented Sep 6, 2019

useRef返回的值在渲染之间是稳定的 - 它不会改变。

@Genluo
Copy link
Owner Author

Genluo commented Sep 6, 2019

@Genluo
Copy link
Owner Author

Genluo commented Sep 7, 2019

Context使用流程(需要和组件组合控制反转方式进行对比从而判断是否需要引入这种方式)
image

image

@Genluo
Copy link
Owner Author

Genluo commented Sep 9, 2019

const App: React.FC<{ title: string }> = ({ title }) => {
  return React.useMemo(() => <div>{title}</div>, [title]);
};

App.defaultProps = {
  title: 'Function Component'
}

推荐使用 React.useMemo 而不是 React.memo,因为在组件通信时存在 React.useContext 的用法,这种用法会使所有用到的组件重渲染,只有 React.useMemo 能处理这种场景的按需渲染。

image

hooks性能优化:https://juejin.im/post/5d75ae7a6fb9a06b0f2407e8

@Genluo
Copy link
Owner Author

Genluo commented Sep 9, 2019

@Genluo
Copy link
Owner Author

Genluo commented Sep 9, 2019

useEffect 注意事项
事实上,useEffect 是最为怪异的 Hook,也是最难使用的 Hook。比如下面这段代码:

useEffect(() => {
  props.onChange(props.id)
}, [props.onChange, props.id])

复制代码如果 id 变化,则调用 onChange。但如果上层代码并没有对 onChange 进行合理的封装,导致每次刷新引用都会变动,则会产生严重后果。我们假设父级代码是这么写的:

class App {
  render() {
    return <Child id={this.state.id} onChange={id => this.setState({ id })} />
  }
}

复制代码这样会导致死循环。虽然看上去 只是将更新 id 的时机交给了子元素 ,但由于 onChange 函数在每次渲染时都会重新生成,因此引用总是在变化,就会出现一个无限死循环:
新 onChange -> useEffect 依赖更新 -> props.onChange -> 父级重渲染 -> 新 onChange...

想要阻止这个循环的发生,只要改为 onChange={this.handleChange} 即可,useEffect 对外部依赖苛刻的要求,只有在整体项目都注意保持正确的引用时才能优雅生效。

然而被调用处代码怎么写并不受我们控制,这就导致了不规范的父元素可能导致 React Hooks 产生死循环。

解决这个有两种方法

  • 方法一: 深比较
// site: https://github.com/streamich/react-use/blob/master/docs/useDeepCompareEffect.md
import {useCounter, useDeepCompareEffect} from 'react-use';

const Demo = () => {
  const [count, {inc: inc}] = useCounter(0);
  const options = { step: 2 };

  useDeepCompareEffect(() => {
    inc(options.step)
  }, [options]);

  return (
    <div>
      <p>useDeepCompareEffect: {count}</p>
    </div>
  );
};

// usage
useDeepCompareEffect(effect: () => void | (() => void | undefined), deps: any[]);
  • 方法二:使用useRef进行处理
function useCurrentValue<T>(value: T): React.RefObject<T> {
  const ref = React.useRef(null);
  ref.current = value;
  return ref;
}

const App: React.FC = ({ onChange }) => {
  const onChangeCurrent = useCurrentValue(onChange)
};

文章

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant