React: Advertencia para: PropTypes.object.isRequired cuando prop es `null`

Creado en 16 feb. 2015  ·  37Comentarios  ·  Fuente: facebook/react

Como PropTypes se trata del 'tipo' de prop, null es un objeto vacío, pero sigue siendo un tipo de objeto, prácticamente.

Pero aún advierte:

 Warning: Required prop `profile` was not specified in `Element`. Check the render method of `OtherElement`.

No creo que se suponga que esto suceda.

Deja de advertir después de que ya no sea null . Estoy bastante seguro de que solo debería advertir cuando sea undefined ?

Comentario más útil

Un caso de uso común que veo es React renderizar un componente antes de que finalice una llamada de API para datos. El primer renderizado representaría, por ejemplo, una lista de elementos ( items: null ). Luego, la llamada a la API finaliza y ahora items se completa con una matriz.

Todos 37 comentarios

null es el equivalente a ningún valor y no es un objeto (vacío o no). Si no desea que advierta por null , no lo haga obligatorio, tiene el mismo efecto. No recomendaría probar la presencia de una clave.

Estoy de acuerdo. No puedo pensar en muchos casos de uso en los que desearía obligar a un usuario a especificar un valor, pero estaría dispuesto a aceptar nulo como valor válido. A efectos prácticos, la advertencia isRequired para nulo es un comportamiento sensible y esperado.

relacionado: https://github.com/facebook/react/issues/2166
(este problema sigue apareciendo de forma destacada en los resultados de búsqueda)

Un caso de uso común que veo es React renderizar un componente antes de que finalice una llamada de API para datos. El primer renderizado representaría, por ejemplo, una lista de elementos ( items: null ). Luego, la llamada a la API finaliza y ahora items se completa con una matriz.

Estoy tratando de hacer PropTypes.oneOfType([null, PropTypes.object]).isRequired , entonces, ya sea nulo o un objeto, ¿no es posible en este momento?

Según el CHANGELOG , desde 15.4.0 se supone que es posible

En realidad, es lo contrario en 15.4.0: Required PropTypes now fail with specific messages for null and undefined.

También me enfrento a este problema.
La solución alternativa de @Noitidart no me funciona. Lanza un error que dice:
Failed prop type: The prop valor is marked as required in Seleccione , but its value is null .

Me parece realmente útil requerir una propiedad pero también permitir valores nulos.

+1 por permitir null alguna manera.

Tenemos un caso de uso en el que nuestra configuración se carga a través de JSON, y hay varias opciones de configuración de etiquetas que especifican una cadena que debe mostrarse, algo como esto:

{
  "title": "my title"
}

Entonces, cuando no se debe mostrar ningún título, usamos null para denotar ese caso:

{
  "title": null
}

(Agregar paralelo hasTitle: false sería prohibitivo ya que tenemos docenas de estas configuraciones).

Para el contenido JSON, el uso de nulo es una forma muy útil de distinguir entre no definido ( undefined ) y omitido deliberadamente ( null ).

puede permitir nulo, establecer propType para que no sea obligatorio, ya que no es obligatorio: P

@jquense gracias eso es muy útil! Eliminé mi comentario anterior porque esta respuesta SO decía lo mismo.

@jquense puede permitir nulos Y indefinidos, pero ni uno ni el otro.

¡Ese es todo el problema! Javascript proporcionó estas 2 construcciones diferentes por una razón, por lo que obligar a todos a tratar null === undefined por PropTypes es una limitación artificial.

El hecho de que quiera que un PropType permita explícitamente null no significa que deba permitir undefined también. Son dos casos distintos, y el lenguaje los diseñó así a propósito.

Tengo un PR para solucionar este descuido aquí: https://github.com/facebook/prop-types/pull/90

Quiero rechazar undefined porque eso significa que hay un error tipográfico y permitir null porque eso significa que la persona que llama pasó explícitamente null . Ese es el punto de este problema. Entiendo que este problema está cerrado porque se recomienda simplemente cambiar a flujo, que analizaré.

@binki Una forma de permitir null pero no undefined es usar su propia función de validación PropType.

En el siguiente ejemplo, solo se permite null o string . La biblioteca PropTypes usa typeof internamente para verificar cadenas, así que hice lo mismo. Un beneficio es que puede mover esta función fuera de su componente y llamarla según sea necesario.

static propTypes = {
  id: PropTypes.number.isRequired,
  email: function(props, propName, componentName) {
    const propValue = props[propName] // the actual value of `email` prop
    if (propValue === null) return
    if (typeof propValue === 'string') return
    return new Error(`${componentName} only accepts null or string`)
  }
}

Supongo que esta solución se desvía de la intención de la biblioteca PropTypes; la razón por la que digo esto se debe al siguiente código de la biblioteca PropTypes en https://github.com/facebook/prop-types/blob/master/factoryWithTypeCheckers.js # L189.

Antes de validar realmente, se realiza una verificación rápida en la que las propiedades establecidas con isRequired arrojan automáticamente un error si el valor de la propiedad es null . En otras palabras, creen que una propiedad requerida que es nula es errónea, mientras que considero que es un caso de uso válido tener nulos requeridos.

if (props[propName] == null) {
  if (isRequired) {
    if (props[propName] === null) {
      return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
    }
    return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
  }
  return null;
} else {
  return validate(props, propName, componentName, location, propFullName);
}

Estoy de acuerdo con @ jharris4 por las razones expuestas. null no es lo mismo que undefined . Es estándar usarlo como marcador de posición.

Desde Mozilla Developer Network:

El valor nulo representa la ausencia intencional de cualquier valor de objeto.

null no es un identificador de una propiedad del objeto global, como puede ser undefined. En cambio, nulo expresa una falta de identificación, lo que indica que una variable no apunta a ningún objeto. En las API, el valor nulo a menudo se recupera en un lugar donde se puede esperar un objeto, pero ningún objeto es relevante.

Se debe permitir null, al menos hasta PropTypes.oneOfType([null, PropTypes.string]).isRequired .

@jquense - Eliminar isRequired significa que probablemente debería establecer un valor predeterminado. ¿Significa esto que ahora estaría configurando un valor predeterminado para el valor inicial en el componente _y_ en el reductor, todo para evitar permitir null como valor para un accesorio?

Tengo un montón de data || '' ( isRequired acepta cadena vacía '' , objeto vacío {} , etc.) en mis selectores porque mientras espero llamadas API a finish null es lo perfecto para decirle al componente que los datos están llegando, ¡solo espere un poco! (pero no puedo hacer eso ...)
@ puiu91 tiene un buen trabajo por ahora ... Tendré una función de utilidad para usar en nuestro código base ... ya que parece que este problema no se volverá a abrir pronto suspiro

También estoy de acuerdo en que debería haber una forma estándar de aceptar null como valor, por las mismas razones que indicaron @ jharris4 y @Findiglay , pero este ya no es el lugar para continuar la discusión. Este problema no solo está cerrado, sino que pertenece a facebook / prop-types . Estoy siguiendo la solicitud de extracción aquí facebook / prop-types # 90.

Protuberancia. Todavía me encuentro con esto hoy. Sería genial tener soporte integrado para algo como:

myObj: PropType.object.isRequiredOrNull :)

Creo que la prioridad en esto es muy baja. Flow es la forma recomendada de ir juntos. http://flow.org/

@Marujah, tu fragmento no es correcto.

Intente pasar nulo al componente y verá que obtendrá la advertencia:

Warning: Failed prop type: The prop 'theProp' is marked as required in 'TheComponent', but its value is null.

El problema es que isRequired se evalúa PRIMERO y nunca dejará pasar valores nulos o indefinidos.

El PR para tipos de accesorios para solucionar el problema está vinculado arriba si está interesado.

¡Oh de verdad! probado de nuevo tienes razón

Exigir que se proporcione específicamente un valor o nulo debe estar absolutamente permitido a través de PropTypes.

Este es el caso de uso con el que me estoy encontrando. Tenemos algunas devoluciones de llamada que son requeridas por el 90% de nuestros selectores. Los pocos que no los necesitan son casos de uso muy específicos. Tenemos algunos desarrolladores nuevos que se olvidan constantemente de proporcionar todas las devoluciones de llamada habituales.

Quiero forzar todos los usos de estos Componentes para tomar la decisión consciente de no incluir devoluciones de llamada específicas, en lugar de que alguien simplemente se olvide de algunos accesorios.

Sí, podemos piratear nuestras propias comprobaciones más específicas a través del flujo, pero eso divide nuestra validación de accesorios en dos lugares, y es bastante poco intuitivo para alguien que eche un vistazo a las definiciones de propTypes.

Solo quería agregar mi caso de uso aquí. Tengo una tienda redux con datos junto con cuándo se obtuvieron esos datos, si hubo un error, etc. Mi componente requiere un accesorio de 'error' (para que pueda mostrar el error al usuario si no se pudieron obtener los datos), que es nulo cuando los datos se cargan correctamente, pero se completa cuando hay un error.

Estoy pasando un componente de cargador ( PropTypes.node ) como props , y cuando no quiero renderizar un cargador, paso null .
Afaik, una función render debería devolver null lugar de undefined cuando no se renderiza nada. Entonces, pasar null como el valor parece la forma correcta de hacerlo para mí.

Estaba implementando el componente InputNumber (envoltorio para <input type="number"> ), así que tenía propTypes para mi prop value - PropTypes.number.isRequired , y cuando usé mi componente, siempre le pasó la propiedad. Pero hoy necesito pasar allí un enlace anulable por defecto al valor, y mi componente agrega una advertencia. La única decisión que puedo imaginar es cambiar propTypes por mi prop value a PropTypes.oneOfType([PropTypes.number, PropTypes.string]) y establecer defaultProps como nulo. Pero creo que no es el correcto porque el tipo de entrada = número debería funcionar solo con números.

Estoy tratando de hacer PropTypes.oneOfType([null, PropTypes.object]).isRequired , entonces, ya sea nulo o un objeto, ¿no es posible en este momento?

Espera una función: Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.

Entonces, debe proporcionar una función, como:

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

Habiendo encontrado este error, escribí una función de conveniencia para solucionarlo:

function nullable(subRequirement) {
  const check = (required, props, key, ...rest) => {
    if (props[key] === null) {
      return null;
    }
    const sub = required ? subRequirement.isRequired : subRequirement;
    return sub(props, key, ...rest);
  };
  const fn = check.bind(null, false);
  fn.isRequired = check.bind(null, true);
  return fn;
}

Uso:

static propTypes = {
  someCallbackFunction: nullable(PropTypes.func).isRequired,
};

Es posible (pero bastante inútil) usar nullable sin isRequired . La razón por la que lo hago compatible con isRequired es para que funcione con la regla react/require-default-props eslint.

Mi caso de uso es una serie de componentes que se ajustan a una API común, envueltos por un solo componente que maneja las devoluciones de llamada. null devoluciones null s. Al mismo tiempo, es importante que todas las propiedades se pasen a los subcomponentes para garantizar que, si se agrega una nueva propiedad, no se pierda. Tampoco quiero proporcionar defaultProps de nulo para cada componente que se ajuste a esta API; hasta donde ellos saben, la persona que llama debe haber especificado un valor.

Tomé el ayudante que escribí antes y lo puse en un paquete junto con un montón de pruebas para demostrar la exactitud:

npm install --save git+https://github.com/davidje13/prop-types-nullable.git#semver:^1.0.0

Uso:

import PropTypes from 'prop-types';
import nullable from 'prop-types-nullable';

[...]

static propTypes = {
  thing: nullable(PropTypes.string).isRequired,
};

Nueva solución: PropTypes.oneOfType([PropTypes.object]).isRequired

Recibo un error.
como arreglar.

ADVERTENCIA en ./~/prop-types/prop-types.js Dependencias críticas: 1: 482-489 Esto parece ser un archivo javascript prediseñado. Aunque esto es posible, no se recomienda. Intente solicitar la fuente original para obtener mejores resultados. @ ./~/prop-types/prop-types.js 1: 482-489

Estoy tratando de hacer PropTypes.oneOfType([null, PropTypes.object]).isRequired , entonces, ya sea nulo o un objeto, ¿no es posible en este momento?

Espera una función: Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.

Entonces, debe proporcionar una función, como:

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

En realidad tuve un error debido a que 'isRequired' al final, ser nulo y obligatorio al mismo tiempo no es compatible ...
Esto es lo que funcionó para mí:

PropTypes.oneOfType([ 
    PropTypes.string.isRequired, 
    () => null 
])

@ gugol2 tenga en cuenta que lo que ha escrito simplemente deshabilitará la verificación de tipo por completo (ahora puede pasar un número a ese accesorio, o undefined , o cualquier cosa); la función que proporcione debe devolver null si la validación se realiza correctamente y no null si falla.

Si desea seguir esa ruta, necesitará algo más como:

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

Por supuesto, podría predefinir la función auxiliar de aspecto desagradable:

const nullable = (props, key) => props[key] === null ? null : 'Not null'

// ...

PropTypes.oneOfType([PropTypes.string.isRequired, nullable])

También es extrañamente posible (¡pero realmente no lo recomendaría!) Usar PropTypes.oneOfType([PropTypes.string.isRequired]) . Sin embargo, esto se siente como un error y no esperaría que un código como ese sobreviva a versiones posteriores. También tenga en cuenta que es similar, pero no igual, a un método sugerido anteriormente que no funciona.


Si puede esperar, hay un RP abierto que se está moviendo increíblemente lento pero aparentemente todavía está en consideración.

Y hasta que el PR se fusione, recomendaría usar el paquete que creé (o el código detrás de él ) porque de esa manera puedes poner .isRequired al final de la línea, lo que lo hace compatible con las reglas de linting.

En mi humilde opinión, este es un comportamiento correcto, pero debería estar documentado.

Un caso de uso común que veo es React renderizar un componente antes de que finalice una llamada de API para datos. El primer renderizado representaría, por ejemplo, una lista de elementos ( items: null ). Luego, la llamada a la API finaliza y ahora items se completa con una matriz.

¿Alguna mejor manera de manejar esto? Quiero que se requiera este accesorio, PERO es nulo antes de recuperarlo de la API.

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

@ davidje13 Encuentro un pequeño problema con este enfoque. La prueba de cobertura tiene 1/4 de caso que nunca está cubierto.

Digamos que tengo un componente Login que solo tiene un prop 'nombre' que puede ser nulo o una cadena requerida:

const Login = ({name}) => {
  return <div>{name}</div>
} 

Entonces sus proptipos son:

Login.propTypes = {
  name: PropTypes.oneOfType([
    PropTypes.string.isRequired,
    (props, key) => (props[key] === null ? null : 'Not null'),
  ]),
};

Cuando pruebo este componente, realmente solo tengo 2 escenarios, nulo O una cadena requerida.

render(<Login name={null} />
render(<Login name={'anyName'} />

Pero la cobertura me dice que mi prueba tiene solo un 75% de cobertura.
Me pregunto cuál será el enfoque oficial para esto.

¿Parece que el caso de prueba que falta es el que falla en la verificación de accesorios? es decir, si pasa un número o indefinido o algo más, no debería haberlo hecho.

¿Parece que el caso de prueba que falta es el que falla en la verificación de accesorios? es decir, si pasa un número o indefinido o algo más, no debería haberlo hecho.

No, no es eso.

Pasar indefinido no amplía la cobertura.
Y no puedo pasar un número de todos modos, no es un valor permitido.

No puedo cubrir ese caso.

¿Fue útil esta página
0 / 5 - 0 calificaciones