如何在React经典的“类”组件中使用React钩子?

时间:2018-11-19 09:09:17

标签: javascript reactjs react-hooks

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

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

问题是我是否可以在其中添加React钩子。我知道React-Hooks可以替代React Class样式。但是,如果我希望慢慢迁移到React挂钩中,可以在类中添加有用的挂钩吗?

12 个答案:

答案 0 :(得分:10)

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

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

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

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

MyDiv = withMyHook(MyDiv);

答案 1 :(得分:9)

类组件不支持钩子-

根据Hooks-FAQ

  

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

答案 2 :(得分:3)

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

根据React FAQs

  

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

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

答案 3 :(得分:2)

正如其他答案已经解释的那样,钩子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>;
}

答案 4 :(得分:2)

状态组件或容器或基于类的组件曾经支持React Hooks的功能,因此我们不需要仅在无状态组件中就在Stateful组件中使用React Hooks。

一些其他信息

什么是React Hook? 那么什么是钩子?钩子是一种新方法,或者为我们提供了编写组件的新方法。

到目前为止,我们当然有基于功能和基于类的组件,对吗?功能组件会收到道具,然后您返回一些应该在屏幕上呈现的JSX代码。

它们非常适合呈现,因此对于呈现UI部分而言,与其说是有关业务逻辑,不如说是太多,它们通常专注于每个组件的一种或几种用途。

另一方面,基于类的组件也将接收道具,但它们也具有此内部状态。因此,基于类的组件是实际上包含我们大多数业务逻辑的组件,因此对于业务逻辑,我的意思是像我们发出HTTP请求之类的事情,我们需要处理响应并更改应用程序的内部状态,或者也许即使没有HTTP。用户填写表单,我们希望将其显示在屏幕上的某个地方,为此我们需要状态,为此我们需要基于类的组件,因此,我们通常还使用基于类的组件来编排我们的其他组件并向下传递我们的状态作为功​​能组件的支撑。

现在,这种分离带来了一个问题,它带来了所有好处,但是我们遇到的一个问题是,从一种成分形式转换为另一种成分形式很烦人。并不是很困难,但是很烦人。

如果您遇到了需要将功能组件转换为基于类的组件的情况,那么这会涉及很多类型的输入,并且总是会进行许多相同类型的输入,因此很烦人。

用引号引起的更大问题是生命周期挂钩可能很难正确使用。

很显然,添加componentDidMount并在其中执行一些代码并不难,但是知道要使用哪个生命周期钩子,何时以及如何正确使用它,尤其在更复杂的应用程序中,无论如何,这都是一个挑战。如果我们有一种创建组件的方式,那么超级组件可以同时处理状态和副作用(如HTTP请求)并呈现用户界面,那很好吗?

好吧,这正是钩子的全部含义。挂钩为我们提供了一种创建功能组件的新方法,这很重要。

答案 5 :(得分:1)

现有的班级组件将无法实现。您必须将您的类组件转换为功能组件,然后在-

function MyDiv() {
const [sampleState, setSampleState] = useState('hello world');
return (
      <div>{sampleState}</div>
    )
}

答案 6 :(得分:1)

React Hooks使您无需编写类即可使用react功能和生命周期。 就像类组件的等效版本一样,它的外形尺寸更小且可读。您应该迁移到React钩子,因为编写它很有趣。 但是,您不能在类组件内部编写react挂钩,因为它是为功能组件引入的。

可以轻松将其转换为:

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

const MyDiv = () => {
   const [sampleState, setSampleState] = useState('hello world');
   return <div>{sampleState}</div>
}

答案 7 :(得分:1)

您可以使用react-universal-hooks库。它使您可以在类组件的render函数中使用“ useXXX”函数。

到目前为止,对我来说效果很好。唯一的问题是,由于它不使用官方的钩子,因此这些值不显示react-devtools。

为了解决这个问题,我通过包装钩子并让它们在component.state.hookValues上存储它们的数据(使用对象突变来防止重新渲染)来创建等效项。 (您可以通过自动包装组件render函数来运行集合currentCompBeingRendered = this来访问组件)

有关此问题的更多信息(以及解决方法的详细信息),请参见此处:https://github.com/salvoravida/react-universal-hooks/issues/7

答案 8 :(得分:0)

对我来说React.createRef()很有帮助。

例如:

constructor(props) {
      super(props);
      this.myRef = React.createRef();
   }

...


<FunctionComponent ref={this.myRef} />

原始帖子here

答案 9 :(得分:0)

补全Joel Cox's good answer


Render Props还允许在类组件内部使用Hooks,如果需要更大的灵活性的话:

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);
}

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

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

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

来源:React Training

答案 10 :(得分:0)

,但不是直接。

尝试一下react-iifc,更多内容请参见自述文件。

https://github.com/EnixCoda/react-iifc

答案 11 :(得分:0)

  1. 尝试使用组件挂钩: https://github.com/bplok20010/with-component-hooks
import withComponentHooks from 'with-component-hooks';


class MyComponent extends React.Component {

    render(){
        const props = this.props;
        const [counter, set] = React.useState(0);

        //TODO...

    }
}

export default withComponentHooks(MyComponent)

2. 试试 react-iifc: https://github.com/EnixCoda/react-iifc