How to access ref or focus to an material-ui/KeyboardDatePicker? - reactjs

I try change the page focus to a single Datepicker component from material-ui (https://material-ui-pickers.dev/api/KeyboardDatePicker).
There, they clearly stated that any ref props will be forwarded to root component (whatever it is). So I assume it will behave like any typical input. But any attempt to access ref will throw an error: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
// THIS DOESN'T
<KeyboardDatePicker
clearable
ref={this.inputs.birth_date}
value={this.state.birth_date}
onChange={this.handleChangeDate}
/>
// THIS WORKS
<input ref={this.inputs.birth_date} />

This appears to be a bug in the library. Fix is available in v4.0.0-alpha.4
https://github.com/mui-org/material-ui-pickers/issues/1303

Related

is <this.props.Component /> a correct syntax in React JSX?

I have a strange case where I used code splitting within React SPA.
My code needs to render sometimes thin component, and in other cases a full component (for logged-in users).
now, Component has been sent to the class as part of props, and within render function I'm trying to render:
<this.props.Component />
and, here is the strange case. sometimes this line of code throws error:
error Cannot read property 'Component' of undefined
with stack trace that pointing to this line. In other cases it works perfectly.
Could anyone explain if this syntax is wrong? or maybe what causes it not to work sometimes?
Seems that the correct answer is that this syntax is not allowed (as of React 16),
I still can't understand why it had worked for me,
but if someone needs to render a component based on props he gets, he has to do it this way (thanks to #David):
{this.props && this.props.Component({
onClickHandler: this.onClick,
currentUser: this.props.currentUser,
etc..
})}
and type of Component must be a function.
another option to whom may want to write pure JSX:
const { Component } = this.props
return (
<Component
currentUser={this.props.currentUser}
onClickHandler={this.onClick />
)

Test Nested Tag attribute inside Parent Tag's attribute

I have a tag that is nested inside another tag's attribute.
Exhibit a.
<Tag
input={(
<NestedTag
value={this.props.value}
onChange={this.validate}
/>
)}
/>
What I want to do is check that value inside NestedTag is correct.
In Enzyme, I've got as far as this:
expect(
wrap
.find(Tag)
.at(0)
.prop('input')
).toBe(...tag info goes here);
This is as far as I've gotten so far. I just don't know how to look inside "input" and poke around inside NestedTag.
I know I can use toMatchObject, but I've prefer to check each individual property in isolation.
As per my comment, if Tag is rendering its input prop as a child, you can simply find it provided that the component is mounted first.
Cheers!

How can I focus on a react-select component at will?

Using react-select v2, I want to show and focus on the Select element when the user hits a certain key. Following are some things I've tried or paths I've gone down.
When I set a ref to the Select element and try to call .focus on it, it says no focus function is found. Perhaps I should somehow get a child element of it and then call focus on that?
There doesn't seem to be any prop I can pass that will trigger a focus function. There is an openOnFocus but not a focusOnOpen. The only thing I can think of would be to enable autoFocus and then somehow trigger a remount but there doesn't seem to be a simple way to do this and it feels hacky. Alternatively, I could enable just create the Select component each time the key is pressed instead of showing it, then unmount it instead of hiding it.
How can I properly get the react-select element to gain focus when I want it to?
I'm using a wrapper component around my component. Here's the render method for my wrapper:
render() {
return (
<Select
options={this.props.options}
value={this.state.value}
ref={this.selectRef}
/>
);
}
And here's where I'm calling that wrapper:
<Wrapper
options={this.props.labelOptions}
ref={this.wrapperRef}
/>
I then try calling focus using either this.dropdownNode.focus() or this.dropdownNode.current.focus() and both say no focus method is found.
Because you're wrapping the Select component, you can't call Select's .focus() function from the ref you're giving to the wrapper. Since ref is a special kind of prop, the ref for that wrapper is only referring to Wrapper itself, not the component it wraps (Select).
To access the actual Select component's ref, you have to pass a ref down to it as a prop with a different, non-magic name, like innerRef (react-select code actually gives a good example of this as it's accessing the actual input element and focusing on that).
Here's the change that fixed it. Here is the wrapper component where Select is actually used (and it's taking in the ref passed to it):
render() {
return (
<Select
options={this.props.options}
value={this.state.value}
ref={this.props.innerRef}
/>
);
}
And here's the component that's calling that wrapper. In the constructor I'm creating the ref with this.selectRef = React.createRef() then I pass it in as a prop in this render method:
<Wrapper
options={this.props.labelOptions}
innerRef={this.selectRef}
/>
Then I can call focus on the Select component itself by running this.selectRef.current.focus() anywhere I want to.
Notes: Thanks to BoyWithSilverWings answer. This question pertains to React 16.3. There is also a new React.ForwardRefs method but this way seems simpler to me.

WebStorm code inspection to detect when an unknown prop is passed to a React Component

My team really wants syntax highlighting in WebStorm when a component is called with a prop that isn't defined in that component's propTypes.
class MyComponent extends Component {
static propTypes = {foo: PropType.string};
...
}
...
<MyComponent
bar={...} // this line would be marked as a warning/error
foo={"some string"}
/>
Is it possible to create a custom code inspection to perform this? How would we go about it?
WebStorm already offers prop name completion, and warns if a required prop is not being passed, so it seems like all of the necessary information already exists. (See the "Completing component properties" section of React - Help | WebStorm.)
Side note: obviously this wouldn't catch props passed dynamically (e.g. <MyComponent {...someObject} />), but we consider that an anti-pattern anyway.

react willReceiveProps workaround for external library

I'm using a react datepicker component that can be found here. The component is pretty great except for what appears to be an oversight: it does not implement willReceiveProps.
To expound, I create the datpicker as below:
<DateField
dateFormat= { dateFormat}
forceValidDate={true}
defaultValue={startDate || ''}
onChange={this.handleChange.bind(null, 'start_date')}
id="start"
>
<DatePicker
navigation={true}
locale="en"
forceValidDate={true}
highlightWeekends={true}
highlightToday={true}
weekNumbers={true}
weekStartDay={0}
/>
</DateField>
Note above that there is a prop defaultValue which I pass startDate. Now, startDate can and does change for reasons that are sometimes external to the component. That value is passed during a new render() action as per usual. According to react philosophy this shouldn't be a problem.
However, it appears to me as if the value from defaultValue is only ever read once inside DateField. It is read as this.props.defaultValue. Anyone who has ever built a component relying on props should quickly recognize this is a problem. It means that when the prop is changed the new value will not be used.
Because this is a library, I cannot simply implement willReceiveProps. Does anyone know of a good workaround to get this component to either completely reset on a render or some other strategy to deal with what seems to be a big design problem?
They follow the same standards as the <input> component. defaultValue is read only once but there is also value that can be set externally. There is no need for them to use willReceiveProps.
In short, use value instead of defaultValue.
See Uncontrolled Components in React
PS: I am looking a bit into the code and it seems there are also properties text and date apart from value. Since the code (and documentation) has been removed from github, I won't inspect what is the difference between those props.

Resources