React-day-picker: Stateless function as component prop triggers a warning

Created on 9 Jul 2018  Â·  13Comments  Â·  Source: gpbl/react-day-picker

CodeSandbox demo: https://codesandbox.io/s/zqx94zxy0l

Following the example in the documentation, adding a component property raises an error in the console saying:

Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.

Check the render method of DayPickerInput.
in component (created by DayPickerInput)
in div (created by DayPickerInput)
in DayPickerInput (created by Example)
in div (created by Example)
in Example

I've noticed that @gengue had the same issue as well some months ago (Gitter message about it)

Transforming the component passed to the picker to a class seems to fix this problem (see this other example) although it doesn't look good and it's different from what the documentation suggests.

Could you provide a better solution or update the documentation to reflect this? Thanks in advance! :)

Most helpful comment

Hi @matthewmcclatchie, inputProps prop was added to the documentation (see http://react-day-picker.js.org/api/DayPickerInput/#inputProps)
Works for me

import DayPickerInput from 'react-day-picker/DayPickerInput';
import styled from 'styled-components';

const StyledInput = styled.input``;

const MyInput = React.forwardRef((props, ref) => {
  return <StyledInput ref={ref} {...props} />
});

const DatePicker = () => {
  return <DayPickerInput inputProps={{ name: 'myInputName' }} component={MyInput}/>
});

All 13 comments

Hey thanks for reporting this! The problem with stateless function is that we can't know how to focus the input field (reason we use a ref there).

This won't give any error from the v7.1.10, however the field won't be focused when the user picks a day from the calendar. We could add a condition to check if the component is stateless and skip the ref at all...

Hey @gpbl was this fixed in v7.1.10?
As I'm still seeing the same warning in v7.1.10

I'm also seeing the warning in v7.1.10.

Why not use document.querySelector instead of ref as an option?

It's not manipulating the DOM, just selecting a field that has the exact same name as you're passing to the input anyway. That way, I could give the component selector="[name='someFieldName']" or just name="someFieldName", and it would do something as simple as:

document
.querySelector('[name="someFieldName"]')
.focus()

Or is there some way I could just do this myself so long as the warning goes away?

Why not use document.querySelector instead of ref as an option?

This can be a solution, but it is not easy as it seems – since it is possible to change the component of the input element, we really don't know what's inside there, which name it has (if it has one) etc.

A solution could be using findDOMNode, at

get input() {
   return React.findDOMNode(this).querySelector('input')
}

which will cover the most of the cases (but not the ones with multiple input fields in it).

IMHO the best solution would be to use the render props pattern by passing a getInput() prop that the user can customize for getting the input field. This will likely land to the next major release, though...

You're right! That's significantly better.

My reason for not wanting any use of this or ref is because I'm using stateless functional components and prefer not writing components with a this or deal with ref if possible.

Yeah that's legit! Thanks for the suggestion @Sawtaytoes.

I think however I'll change this behavior in the next major release, which will not require much refactoring from you... but it will protect others from breaking changes I can't see now using querySelector :)

Hey, I have the same issue! Any chance I could make this warning go away from my side, without editing the library?

@egloo8 the workaround suggested by @elamperti works great for me; create a component class for your input and pass that one as the component prop on DayPickerInput.

I'm having trouble with the suggested solution since I need to pass a prop to that component:

class MyComp extends React.Component {

  rendertTinyComp () {
    return (<div>an improtant prop: {this.props.imporantProp}</div>)
  }

  render() {
    return (<DayPickerInput component={this.rendertTinyComp}/>) //will result the refs error
  }
}

If I try to define the component from the outsite I can do something like this:

return (<DayPickerInput component={<TinyComp imporantProp={this.prop.imporantProp} />) //will not accept a componet - expects a function

the only way to make it work is to somehow create a class component inside the myComp component which sounds like a bad practice and I'm not sure it's even possible.

This can be done with redux easily probably, but unfortunately I can't use redux in this specific scenario.

Does someone has an idea how to solve this ?

Just wanted to clarify if this issue conflicts with the documentation as well. Getting same error:

http://react-day-picker.js.org/api/DayPickerInput/#component

This code works fine without any warnings:

import DayPickerInput from 'react-day-picker/DayPickerInput';

class Input extends React.Component {
    render() {
        return <input />;
    }
}

class DurationInput extends React.Component {
    render() {
        return (
            <DayPickerInput component={Input}/>
        );
    }
}

Stumbled across this today whilst looking for a solution to the same problem.

Following the guide in the docs and passing the props to the component and returning a new component with the props spread into it (`...props) resulted in the same error.

Both @elamperti and @MrBinWin 's solutions worked for me. In my case however, I was using a Styled Component as the input for the component prop and need to pass some extra props along.

In order to add these extra props, I used the inputProps prop (which I must have missed when looking at the docs) and everything now works!

Hi @matthewmcclatchie, inputProps prop was added to the documentation (see http://react-day-picker.js.org/api/DayPickerInput/#inputProps)
Works for me

import DayPickerInput from 'react-day-picker/DayPickerInput';
import styled from 'styled-components';

const StyledInput = styled.input``;

const MyInput = React.forwardRef((props, ref) => {
  return <StyledInput ref={ref} {...props} />
});

const DatePicker = () => {
  return <DayPickerInput inputProps={{ name: 'myInputName' }} component={MyInput}/>
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

olimination picture olimination  Â·  4Comments

kradical picture kradical  Â·  3Comments

pmartiner picture pmartiner  Â·  3Comments

trevordmiller picture trevordmiller  Â·  4Comments

thebuilder picture thebuilder  Â·  3Comments