如何在 React 经典 `class` 组件中使用 React 钩子?

IT技术 javascript reactjs react-hooks
2021-01-15 14:51:04

在这个例子中,我有这个react类:

class MyDiv extends React.component
   constructor(){
      this.state={sampleState:'hello world'}
   }
   render(){
      return <div>{this.state.sampleState}
   }
}

问题是我是否可以为此添加 React 钩子。我知道 React-Hooks 是 React Class 风格的替代品。但是如果我想慢慢迁移到 React hooks 中,我可以在 Classes 中添加有用的 hooks 吗?

6个回答

在 hooks 出现之前,高阶组件是我们一直在做这种事情的方式。您可以为钩子编写一个简单的高阶组件包装器。

function withMyHook(Component) {
  return function WrappedComponent(props) {
    const myHookValue = useMyHook();
    return <Component {...props} myHookValue={myHookValue} />;
  }
}

虽然这并不是真正直接从类组件使用钩子,但这至少允许您从类组件使用钩子逻辑,而无需重构。

class MyComponent extends React.Component {
  render(){
    const myHookValue = this.props.myHookValue;
    return <div>{myHookValue}</div>;
  }
}

export default withMyHook(MyComponent);
直接给一个类(MyDiv)赋值可以吗?它给出了一个 es-lint 错误!
2021-03-13 14:51:04
在第一个代码块中,不应该在返回行中Component代替MyComponent吗?
2021-03-14 14:51:04
@TusharShukla 覆盖这样的类值在技术上是可以的 - 但通常有点不赞成,是的,eslint 想在默认情况下阻止它。更新了示例以使其更加清晰。
2021-03-19 14:51:04
@NicholasHamilton 不 - 这个例子是正确的。第一个代码块是第二个代码块中类组件的示例高阶组件包装器。在这个例子中,高阶组件包装器使用useMyHook()钩子,并将钩子的结果作为调用myHookValue类组件的 prop 提供
2021-03-24 14:51:04
优秀的答案。我将这种方法用于使用 Hooks 编写的 react-alert 包。
2021-03-30 14:51:04

类组件不支持钩子 -

根据Hooks-FAQ

您不能在类组件内使用 Hook,但您绝对可以在单个树中将类和函数组件与 Hook 混合使用。组件是使用 Hooks 的类还是函数是该组件的实现细节。从长远来看,我们希望 Hooks 成为人们编写 React 组件的主要方式。

我一直React.createRef在课堂上看到,并认为这是React.useRef🤪
2021-03-21 14:51:04
但是让我们记住,我们绝对可以在一个树中混合类和函数组件。
2021-03-28 14:51:04

钩子不是用于类,而是用于函数。如果你想使用钩子,你可以开始编写新代码作为带有钩子的功能组件

根据React 常见问题解答

您不能在类组件内使用 Hook,但您绝对可以在单个树中将类和函数组件与 Hook 混合使用。组件是使用 Hooks 的类还是函数是该组件的实现细节。从长远来看,我们希望 Hooks 成为人们编写 React 组件的主要方式。

const MyDiv = () => {
   const [sampleState, setState] = useState('hello world');
   render(){
      return <div>{sampleState}</div>
   }
}
它是一个简单的数组解构,可以命名为任何东西。setState, setSampleState, setABC
2021-03-29 14:51:04
应该setSampleState不是?
2021-04-04 14:51:04

正如其他答案已经解释的那样,钩子 API 旨在为函数组件提供当前仅在类组件中可用的功能。钩子不应该用在类组件中。

可以编写类组件以更轻松地迁移到功能组件。

使用单一状态:

class MyDiv extends Component {
   state = {sampleState: 'hello world'};

   render(){
      const { state } = this;
      const setState = state => this.setState(state);

      return <div onClick={() => setState({sampleState: 1})}>{state.sampleState}</div>;
   }
}

转换为

const MyDiv = () => {
   const [state, setState] = useState({sampleState: 'hello world'});

   return <div onClick={() => setState({sampleState: 1})}>{state.sampleState}</div>;
}

请注意,useState状态设置器不会自动合并状态属性,这应该用setState(prevState => ({ ...prevState, foo: 1 }));覆盖

具有多个状态:

class MyDiv extends Component {
   state = {sampleState: 'hello world'};

   render(){
      const { sampleState } = this.state;
      const setSampleState = sampleState => this.setState({ sampleState });

      return <div onClick={() => setSampleState(1)}>{sampleState}</div>;
   }
}

转换为

const MyDiv = () => {
   const [sampleState, setSampleState] = useState('hello world');

   return <div onClick={() => setSampleState(1)}>{sampleState}</div>;
}

补充乔尔考克斯的好答案


如果需要更大的灵活性,Render Props还允许在类组件中使用 Hook:

class MyDiv extends React.Component {
  render() {
    return (
      <HookWrapper
        // pass state/props from inside of MyDiv to Hook
        someProp={42} 
        // process Hook return value
        render={hookValue => <div>Hello World! {hookValue}</div>} 
      />
    );
  }
}

function HookWrapper({ someProp, render }) {
  const hookValue = useCustomHook(someProp);
  return render(hookValue);
}

对于没有返回值的副作用 Hooks:

function HookWrapper({ someProp }) {
  useCustomHook(someProp);
  return null;
}

// ... usage
<HookWrapper someProp={42} />

资料来源:react培训