简体   繁体   English

如何指定带有功能组件的构造函数(粗箭头语法)?

[英]How to specify a constructor with a functional component (fat arrow syntax)?

Given this component:鉴于此组件:

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

const NewGoalInput = props => {
  return (
    <input type="text" onKeyUp={handleKeyUp}/>
  )
}

const handleKeyUp = (e) => {
  if (e.key === "Enter") {
    // TODO Add goal
  }
}

export default NewGoalInput

How do I add a constructor where I can define the state without using the extends React.Component syntax?如何在不使用extends React.Component语法的情况下添加可以定义 state 的构造函数?

Since it's a stateless component it doesn't have the component lifecycle.由于它是一个无状态组件,它没有组件生命周期。 Therefor you can't specify a constructor .因此你不能指定一个constructor

You have to extend React.Component to create a stateful component which then will need a constructor and you'll be able to use the state .你必须扩展React.Component来创建一个有状态的组件,然后它需要一个构造函数,你将能够使用state

Update Since React 16.8.0 and Hooks got introduced there are more options.更新自从React 16.8.0和 Hooks 引入以来,有更多选择。

Hooks are a new feature proposal that lets you use state and other React > features without writing a class. Hooks 是一个新的特性提案,它可以让你在不编写类的情况下使用状态和其他 React > 特性。 They are released in React as a part of > v16.8.0它们作为 > v16.8.0 的一部分在 React 中发布

Stateless:无国籍:

import React from "react"

const Stateless = ({name}) => (
  <div>{`Hi ${name}`}</div>
);

Stateful:有状态:

Has access to component lifecycle methods and local state.可以访问组件生命周期方法和本地状态。

class Stateful extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    const { count } = this.state;
    document.title = `You've clicked ${count} times.`;
  }

  componentDidUpdate() {
    const { count } = this.state;
    document.title = `You've clicked ${count} times.`;
  }

  render() {
    const { count } = this.state;
    return (
      <div>
        <p>You've clicked {count} times.</p>
        <button onClick={() => this.setState({ count: count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

Using Hooks:使用钩子:

Able to use State Hook and Effect Hook .能够使用State HookEffect Hook

If you're familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.如果您熟悉 React 类的生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。

import React, { useState, useEffect } from "react";

const UsingHooks = () => {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You've clicked ${count} times.`;
  });

  return (
    // <> is a short syntax for <React.Fragment> and can be used instead of a wrapping div
    <>
      <p>You've clicked {count} times.</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </>
  );
}

Now that we have useState and hooks the answers are kind of out of date.现在我们有了useState和 hooks,答案有点过时了。 I came across this question because I was doing something wrong.我遇到这个问题是因为我做错了什么。 Here's some simplified code of what I was doing.这是我正在做的一些简化代码。

// set an initial state
const [ value, setValue ] = useState(0)

// gets called after component is re-rendered
useEffect(() => {
   // callback to parent that set props
   props.update()
})

// if we have an existing value passed in
if (props.value) {
   setValue(props.value)
}

This code was converted from a stateful class to a function using hooks, originally setting the default props in the constructor - but functions don't have constructors and that check happens every time the component re-renders:这段代码使用钩子从有状态类转换为函数,最初在构造函数中设置默认道具 - 但函数没有构造函数,每次组件重新渲染时都会进行检查:

  1. calls useState调用useState
  2. triggers re-render触发重新渲染
  3. useEffect is triggerd useEffect 被触发
  4. parent is called which sets the props调用 parent 来设置 props
  5. props update so child renders again props 更新,所以 child 再次渲染
  6. GOTO 1转到 1

As you can see this results in an infinite loop.如您所见,这会导致无限循环。 The solution is really quite simple.解决方案真的很简单。 Here's a mock diff from the original.这是与原始版本的模拟差异。

- const [ value, setValue ] = useState(0)
+ const [ value, setValue ] = useState(props.value || 0)

- if (props.value) {
-   setValue(props.value)
- }

Basically, just initialise the state from the props and don't do silly things like calling useState except in response to an event or callback of some type.基本上,只需从 props 初始化状态,不要做诸如调用useState类的愚蠢事情,除非响应某种类型的事件或回调。

You don't.你没有。 The kind of component in your example is called "stateless functional component".您示例中的组件类型称为“无状态功能组件”。 It has no state and no lifecycle methods.它没有状态,也没有生命周期方法。 If you want your component to be stateful you'll have to write it as a class component.如果您希望组件有状态,则必须将其编写为类组件。

To simulate constructor in FC use useEffect.要模拟 FC 中的构造函数,请使用 useEffect。

useEffect(() => {
  ... here your init code
}, []);

That's it!就是这样! EZ! EZ! This useEffect runs only once when the component loads and never runs after, just don't forget to add square brackets at the end.这个 useEffect 在组件加载时只运行一次,之后再也不运行,只是不要忘记在最后添加方括号。

you could set a useState as the first line inside of your functional component and add a function as "initial value":您可以将 useState 设置为功能组件内的第一行,并添加一个函数作为“初始值”:

const MyComponentName = props => {
  useState(() => {
    console.log('this will run the first time the component renders!');
  });
  return <div>my component!</div>;
};

You can use useMemo hook (as below) to demonstrate as constructor for functional component.您可以使用useMemo钩子(如下)来演示作为功能组件的构造函数。 Somebody suggested to use useEffect but it will be invoked after render.有人建议使用useEffect它会在渲染后调用。

useMemo(() => {
  console.log('This is useMemo')
}, []);

For those who want to run a function once before the component is mounted, here is a hook (written in TypeScript).对于那些想安装组件之前运行一次函数的人,这里有一个钩子(用 TypeScript 编写)。

Normally useEffect and useLayoutEffect suffice, but they run after the component is mounted, and sometimes you want to run code before that happens (like a constructor).通常useEffectuseLayoutEffect就足够了,但它们在组件安装后运行,有时您希望在此之前运行代码(如构造函数)。

import React, { useRef } from "react";

function useOnce<Type>(callBack: () => Type): Type {
  const result = useRef<Type | null>(null);

  if (result.current !== null) {
    return result.current;
  }

  result.current = callBack();
  return result.current;
}

const Component: React.FC<{}> = () => {
  const result = useOnce(() => {/* Code you would normally put in a constructor */});

  return <div />
}

Alternatively, you can use react-afc或者,您可以使用react-afc

import { afc, reactive } from 'react-afc'

function heavyCalc() {/*...*/}

const Conponent = afc(props => {
  // Called once, before the first render

  const state = reactive({
    name: 'Stack',
    inputsCount: 0
  })

  // Without useMemo(..., [])
  const result = heavyCalc()

  // The function is created once and does not cause
  // a re-render of child components
  function onInput(e) {
    state.inputsCount++
    state.name = e.currentTarget.value
  }

  // Saved between renders (no longer need useRef)
  let rendersCount = 0

  // Must return the render-function
  return () => {
    // The function works like a regular react-component
    // Here you can use the usual hooks
    rendersCount++
    return (
      <input onChange={onInput} value={state.name}/>
    )
  }
})

The package has the necessary methods for working with state (including redux ), react-hooks , lifecycle methods and context package 具有使用state (包括redux )、 Z541EF72F67F6B7B8生命周期方法3452C80DACC84B8的必要方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在函数组件(胖箭头函数)中使用构造函数? - how can i use constructor in function component (fat arrow function)? ReactJS 组件生命周期方法与粗箭头功能组件 - ReactJS component lifecycle methods with fat arrow functional component 在课堂上绑定构造函数或胖箭头 - Bind in constructor or fat arrow in class 在ES6类方法和非React中使用胖箭头语法与否之间有功能上的区别吗? - Are there any functional differences between using fat arrow syntax or not for ES6 class methods and React? 在反应中导入后,使用粗箭头声明的功能组件变为未定义 - functional component declare using fat arrow becomes undefined after import in react 如何使用函数构造函数将类组件转换为函数式? - How convert class component to functional with function constructor? 具有箭头函数处理程序的功能组件是否比具有构造函数中绑定的处理程序的类组件更好地提高性能? - Is functional component with arrow function handler better for performance then a class component with a handler bound in constructor? 如何指定功能组件的React Day Picker组件的handleDayClick - How to specify handleDayClick of React Day Picker component of a functional component 使用 class 语法的粗箭头语法反应 WebWorker - React WebWorker using fat arrow syntax insted of class syntax 当使用胖箭头功能作为事件处理程序时,如何模拟React组件的事件? - How to mock a react component's event when fat arrow function is used as event handler?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM