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

后端 未结 5 750
南笙
南笙 2020-12-15 16:46

Given this component:

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

const NewGoalInput = props => {         


        
相关标签:
5条回答
  • 2020-12-15 17:24

    Since it's a stateless component it doesn't have the component lifecycle. Therefor you can't specify a 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.

    Update Since React 16.8.0 and Hooks got introduced there are more options.

    Hooks are a new feature proposal that lets you use state and other React > features without writing a class. They are released in React as a part of > v16.8.0

    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.

    If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

    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>
        </>
      );
    }
    
    0 讨论(0)
  • 2020-12-15 17:31

    Now that we have useState and hooks the answers are kind of out of date. 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
    2. triggers re-render
    3. useEffect is triggerd
    4. parent is called which sets the props
    5. props update so child renders again
    6. GOTO 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.

    0 讨论(0)
  • 2020-12-15 17:35

    To simulate constructor in FC use useEffect.

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

    That's it! 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.

    0 讨论(0)
  • 2020-12-15 17:36

    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.

    0 讨论(0)
  • 2020-12-15 17:36

    you could set a useState as the first line inside of your functional component and add a function as "initial value":

    const MyComponentName = props => {
      useState(() => {
        console.log('this will run the first time the component renders!');
      });
      return <div>my component!</div>;
    };
    
    0 讨论(0)
提交回复
热议问题