React-native-web: "name" prop not being passed to Input components

Created on 30 Oct 2020  路  11Comments  路  Source: necolas/react-native-web

The problem
I'm not sure if this is a bug or i missed where this was documented but the "name" prop no longer shows up in the DOM if passed to a TextInput component.

This was working in 0.11.7 but is not working in 0.14.7

How to reproduce
https://codesandbox.io/s/laughing-sanne-jq8vp?fontsize=14&hidenavigation=1&theme=dark

Expected behavior
<TextInput name="email" />

EXPECTED
<input name="email" />

ACTUAL
<input />

Thanks!

Most helpful comment

In both of those examples you could be using any CSS selector, including data attributes set using the dataSet prop

All 11 comments

I'm also running into the same issue. We're using "name" quite extensively in our RN project.

What are you using name for, including in an RN project? The prop isn't part of the public API.

We use it in our cypress tests but it is my understanding that it is used by browsers for auto-filling and accessibility as well. The prop was being passed in 0.11.7 but it seems like a recent update changed that behavior

Yes the behavior change was detailed in the release notes.

You should use autoComplete for auto-filling. The name prop is used as metadata in form submit objects, but that doesn't seem essential when you are using JS to work with forms. So before I add another web-only prop to the API, I want to understand if there is an essential use case

Its just weird having props being filtered out when they could just be passed as-is to DOM. Things like data-name, data-cy, name etc. are used by tests and third party services like Netlify and Google Tag Manager (and probably more). I get that you have to balance the React Native and Web parts of the framework but there should be a way to pass arbitrary props to the DOM.

You can set data attributes.

I'd prefer if people shared and explained use cases.

very well: Our use case is a fairly large code base using RNW with a Google Tag Manager integration and many Cypress tests that use the name field. I can respect if this is a firm design decision and we can adjust those integrations, but if it is possible to whitelist certain variables that would save us a ton of work.

Additionally, in the following code sandbox, it seems like data-* props are not being passed to the input component. Am i doing something wrong?

https://codesandbox.io/s/laughing-sanne-jq8vp?fontsize=14&hidenavigation=1&theme=dark

Our use case is a fairly large code base using RNW with a Google Tag Manager integration and many Cypress tests that use the name field

Please could you help me understand how this prop overlaps with Google Tag Manager. What does that integration look like? And what are examples of how your Cypress tests use this (can paste representative code)?

... it seems like data-* props are not being passed to the input component

The way to do that is using the dataSet prop (equivalent to dataset)

<View dataSet={{ one: 'one' }} />
// => <div data-one="one" />

Although I just noticed this note, which I should probably do for the dataSet prop:

For example, a data-abc-def attribute corresponds to dataset.abcDef.

First off thank you for taking the time to thoroughly explore this!

From my perspective it feels odd to be filtering and mutating props rather than just passing them as is to the DOM. It seems like unnecessary levels of abstraction.

Here is an example of a cypress test that uses the name attributes

  cy.visit("/login");
  cy.get('input[name="email"]').type(email);
  cy.get('input[name="password"]').type(password);

Here is an example of a GTM trigger based on the name attribute
image

The way to do that is using the dataSet prop (equivalent to dataset)

export const getDataSetFromProps = (props: Record<string, any>) => {
  return Object.entries(props)
    .filter(([k]) => k.startsWith('data-'))
    .reduce((acc, [key, val]) => {
      acc[key.substr(5)] = val;
      return acc;
    }, {} as Record<string, any>);
};

or with lodash

import { chain } from 'lodash';

export const getDataSetFromProps = (props: Record<string, any>) => {
  return chain(props)
    .pickBy((_, k) => k.startsWith('data-')) // get all data-* attributes
    .mapKeys((_, k) => k.substr(5)) // map to object without 'data-'
    .value();
};

In both of those examples you could be using any CSS selector, including data attributes set using the dataSet prop

Ok I will refactor. Thanks for taking the time to respond here.

Was this page helpful?
0 / 5 - 0 ratings