32

I want to declare default props in a functional component

normally we would do this

function Body() {
    static defaultProps = {
        counter: 0
    }
    return (
        <div>
            body
        </div>
    );
}

this obviously doesn't work

Max Carroll
  • 4,441
  • 2
  • 31
  • 31
angry kiwi
  • 10,730
  • 26
  • 115
  • 161
  • Do you mean a *hook*, or a *component*? https://stackoverflow.com/questions/47774695/react-functional-component-default-props-vs-default-parameters shows two ways of doing this for stateless functional components – jonrsharpe Jun 19 '19 at 06:53
  • hook component, or component hook, or hook or whatever people call them these days – angry kiwi Oct 17 '19 at 03:05
  • a component and hook are different things, for hooks you cant use defaultProps like this you need to use javascript defaults instead e.g.`function useMyHook({ prop1 = "foo", prop2 = "bar"}) ` – Max Carroll Jun 04 '20 at 16:42
  • What you have above is a functional component, functional components may utilise hooks, but they are not hooks them selves. You can identify a hook as it starts with the word `use` e.g. `useEffect` `useState` or your own custom hook `useMyHook`. The other component type are class components and these may not use hooks they have their own internal state – Max Carroll Jun 04 '20 at 16:46

7 Answers7

50

This is usually called a functional component, not a hook component.

For the defaultProps you can do it like this:

const Body = ({ counter }) => {
    return (
        <div>
            {counter}
        </div>
    );
}

Body.defaultProps = {
    counter: 0
}
Arnaud Christ
  • 3,440
  • 3
  • 24
  • 33
  • This is correct. Please be careful 'default' without 's' e.g. I used Body.defaultsProps previously but after correct it to Body.defaultProps then it worked! Thanks! – KHACHORNCHIT Feb 25 '21 at 09:07
  • 2
    Apparently defaultProps on functional components may be dropped in the future (https://stackoverflow.com/a/56443098, – Carl G Nov 14 '22 at 17:02
30
function Body({counter=0}) {
    return (
        <div>
            body
        </div>
    );
}

counter now has initial value of 0

angry kiwi
  • 10,730
  • 26
  • 115
  • 161
22

You can do that simply like this

const Body = (props) => {
    const {foo = 'defaultValue'} = props;

    return <div>{foo}</div> // It will show defaultValue if props foo is undefined
}
bkm412
  • 1,047
  • 5
  • 11
1

Hooks are just regular functions, you can define default values the same way as you define them in regular functions

function useNameHook(initialName = "Asaf") {
  const [name, setName] = useState(initialName);

  // you can return here whatever you want, just the name,
  // just the setter or both
  return name;
}

function Comp({ name }) {
  const myName = useNameHook(name);

  return <h1>Hello {myName}</h1>;
}

function App() {
  return (
    <div className="App">
      {/* without name prop */}
      <Comp />
      {/* with name prop */}
      <Comp name="angry kiwi" />
    </div>
  );
}
Asaf Aviv
  • 11,279
  • 1
  • 28
  • 45
0

I just implemented a custom hook for this which plays well with Typescript.

Custom hook:

const usePropsWithDefaults = <
  P extends Record<string, unknown>, I extends P, D extends P
>(incomingProps: I, defaultProps: D) => {

  // We need a ref of incomingProps so we can compare previous props to incoming props
  const inRef = React.useRef<P>(incomingProps);

  // We need a ref of result because we might want to return exactly the same object if props object has not changed
  const outRef = React.useRef<P>({ ...defaultProps, incomingProps });

  // props object has changed so we can return a new object which is a spread of defaultProps and incomingProps
  if (inRef.current !== incomingProps) {
    inRef.current = incomingProps;
    outRef.current = { ...defaultProps, ...incomingProps };
    return outRef.current as I & D;
  }

  // one or more props have changed.
  Object.assign(outRef.current, incomingProps);
  return outRef.current as I & D;
}

Implementation:

export type Props = {
  one: string;
  two?: number;
  three: boolean;
  four?: string;
};

export const defaultProps = {
  one: '',
  two: 2,
  three: false,
} satisfies Partial<Props>;

const myComponent = (incomingProps: Props) => {
  const props = usePropsWithDefaults(incomingProps, defaultProps);
  // ...
}
Stephen Paul
  • 37,253
  • 15
  • 92
  • 74
-1

You can declare defaultProps outside the functional component. In your case it would be something like this -

   function Body(props) {
    return (
        <div>
            {props.counter}
        </div>
    );
  }
  Body.defaultProps = {
      counter: 0
  }
Max Carroll
  • 4,441
  • 2
  • 31
  • 31
Zubayer Himel
  • 65
  • 1
  • 11
-1

This is for hooks but is not intended for functional components.

const defaultProps = {
  position: "end"
};

const Dropdown = (props) => {
   // The order of arguments is important.
  props = Object.assign({}, defaultProps, props);
  ...
}