We have a use case where we have two TextFields and their heights are being matched. The current way we're accomplishing this is by using a ref to get the height of the TextFields from the DummyInput and passing back the larger of the two.
With the 3.6.0 version, TextField is now being wrapped with withAppProvider meaning that the ref is no longer being set on the component and it is breaking our section since we can't do ref.current.input to get the height.
I have two solutions in mind and have seen them used in the current code base:
Use the withRef higher-order component with compose in TextField so that refs can be forwarded to the component. Keeping the functionality of our use case.
Add a data-height attribute on the component that will give the user the height that the component calculates so that we don't have to use a ref.
I'm leaning towards solution 2 because, at least for our use case, we just need the calculated height of the textfields. The use case with using a ref would probably be where someone needs to modify the element and I'm not sure that's something we would want to let happen.
Is there any reason that wrapping the input in a div, placing the ref on that div, and getting the height from that would not work?
Is there any reason that wrapping the input in a
div, placing therefon thatdiv, and getting the height from that would not work?
clientHeight doesn't include margin or border so that may be a viable option.
If you can't use Dan's suggestion I'm in favour of option one. It's the "react" way of doing things and using a ref only isn't an option anymore because of "wrapper hell"
Thanks, placing the ref of the div works 馃憤
What if one wanted to use https://github.com/text-mask/text-mask/tree/master/react#customize-rendered-input-component with a TextField from Polaris? The library needs access to the input DOM node to manage masking.
@raunofreiberg I'm not familiar with text-mask, but on a quick glance it appears to be an abstraction on top of the pattern property. We expose a pattern prop on TextField, which translates directly to the pattern attribute on the input element. Is there any reason that does not fit your use-case?
The pattern attribute doesn't seem to mask the input. What I exactly have in mind is the date input here: https://text-mask.github.io/text-mask/
Typing in the input helps you just fill in the blanks for the date with a nice UX.
Yup, agreed that is a nice UX, and not achievable in the current implementation. This may even be something worth supporting natively in the component.
@AndrewMusgrave what would it look like to implement ref forwarding with WithRef HOC? Are there other components where access to the underlying DOM node might be useful?
it's also not possible to use https://react-hook-form.com/ because it requires to register inputs via ref prop.
please also see #1918
@sijad Do you in anyhow found any way to use react-hook-form? If not, what form validation library would you recommend to use?
@andychong1996 unfortunatly no. I'm using Formik v2 + Fonk in my project.
yup is more popular validator but Fonk was simpler.
for formik you can also use this projec: t: https://github.com/SatelCreative/formik-polaris
Reaching into components is something that Polaris doesn't recommend since it's likely that a future upgrade will eventually break something. If your deadset on using react hook form, you can still access the input element using web api's. If you need to register the input element multiple times, you may want to look into using a mutation observer as well.
import React, { useCallback, useState, useEffect } from "react";
import { TextField } from "@shopify/polaris";
function Input({ children, id }) {
const [inputNode, setInputNode] = useState();
useEffect(() => {
setInputNode(document.querySelector('input'));
}, [id]);
return children(inputNode);
}
export default function TextFieldExample() {
const [value, setValue] = useState("Jaded Pixel");
const id = "my-text-field";
const handleChange = useCallback(newValue => setValue(newValue), []);
return (
<Input>
{inputNode => {
console.log(inputNode);
return (
<TextField id={id} label="Store name" value={value} onChange={handleChange} />
);
}}
</Input>
);
}
With that being said, we don't recommend reaching into components 馃槃
Most helpful comment
it's also not possible to use https://react-hook-form.com/ because it requires to register inputs via
refprop.please also see #1918