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

Ami*_*ein 16 javascript reactjs react-hooks

在这个例子中,我有这个反应类:

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

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

Joe*_*Cox 25

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

function withMyHook(Component) {
  return function WrappedComponent(props) {
    const myHookValue = useMyHook();
    return <Component {...props} myHookValue={myHookValue} />;
  }
}
Run Code Online (Sandbox Code Playgroud)

尽管这并不是真正地直接使用类组件中的钩子,但这至少将允许您使用类组件中的钩子逻辑,而无需重构。

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

MyDiv = withMyHook(MyDiv);
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。我将这种方法用于使用 Hooks 编写的react-alert 包。 (4认同)

小智 9

类组件不支持挂钩 -

根据Hooks-FAQ:

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


for*_*d04 6

补充乔尔·考克斯的好答案


如果需要更大的灵活性, 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

// ... usage
<HookWrapper someProp={42} />
Run Code Online (Sandbox Code Playgroud)

来源:React 培训


Shu*_*tri 5

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

根据React 常见问题解答

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

const MyDiv = () => {
   const [sampleState, setState] = useState('hello world');
   render(){
      return <div>{sampleState}</div>
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 它应该是`setSampleState` 不是吗? (4认同)
  • 它是一个简单的数组解构,可以命名任何东西。setState、setSampleState、setABC (4认同)

Est*_*ask 5

正如其他答案已经解释的那样,钩子 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>;
   }
}
Run Code Online (Sandbox Code Playgroud)

转换为

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

   return <div onClick={() => setState({sampleState: 1})}>{state.sampleState}</div>;
}
Run Code Online (Sandbox Code Playgroud)

请注意,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>;
   }
}
Run Code Online (Sandbox Code Playgroud)

转换为

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

   return <div onClick={() => setSampleState(1)}>{sampleState}</div>;
}
Run Code Online (Sandbox Code Playgroud)


Muh*_*man 5

您可以通过通用高阶组件来实现这一点

HOC

import React from 'react';
const withHook = (Component, useHook, hookName = 'hookvalue') => {
  return function WrappedComponent(props) {
    const hookValue = useHook();
    return <Component {...props} {...{[hookName]: hookValue}} />;
  };
};

export default withHook;
Run Code Online (Sandbox Code Playgroud)

用法

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

export default withHook(MyComponent, useHook, 'myUseHookValue');
Run Code Online (Sandbox Code Playgroud)