Como PropTypes
é sobre o 'tipo' de objeto, null
é um objeto vazio, mas ainda é um tipo de objeto, praticamente.
Mas ainda assim avisa:
Warning: Required prop `profile` was not specified in `Element`. Check the render method of `OtherElement`.
Eu não acho que isso deveria acontecer.
Ele para de alertar depois que não for mais null
. Tenho certeza que ele só deve avisar quando for undefined
?
null
é o equivalente a nenhum valor e não é um objeto (vazio ou não). Se você não quiser que ele avise por null
então não o torne obrigatório, ele tem o mesmo efeito. Testar a presença de uma chave não é algo que eu recomendaria.
Eu concordo. Não consigo pensar em muitos casos de uso em que você desejaria forçar um usuário a especificar um valor, mas estaria disposto a aceitar null como um valor válido. Para fins práticos, o aviso isRequired para nulo é um comportamento sensato e esperado.
relacionado: https://github.com/facebook/react/issues/2166
(este problema ainda aparece com destaque nos resultados da pesquisa)
Um caso de uso comum que vejo é o React renderizando um componente antes que uma chamada de API para dados seja concluída. A primeira renderização renderia, por exemplo, uma lista de itens ( items: null
). Em seguida, a chamada API termina e agora items
é preenchido com uma matriz.
Estou tentando fazer PropTypes.oneOfType([null, PropTypes.object]).isRequired
, então nulo ou um objeto, isso não é possível agora?
De acordo com o CHANGELOG , uma vez que 15.4.0
é suposto ser possível
Na verdade, é o oposto em 15.4.0: Required PropTypes now fail with specific messages for null and undefined.
Eu também estou enfrentando esse problema.
A solução alternativa de @Noitidart não está funcionando para mim. Ele lança um erro dizendo:
Failed prop type: The prop
value is marked as required in
Selecione , but its value is
null .
Acho muito útil exigir uma propriedade, mas também permitir valores nulos.
1 por permitir null
alguma forma.
Temos um caso de uso em que nossa configuração é carregada via JSON e existem várias opções de configuração de rótulo que especificam uma string que deve ser exibida, algo como isto:
{
"title": "my title"
}
Portanto, quando nenhum título deve ser exibido, usamos null
para denotar esse caso:
{
"title": null
}
(Adicionar hasTitle: false
paralelo seria proibitivo, pois temos dezenas dessas configurações.)
Para conteúdo JSON, usar null é uma maneira muito útil de distinguir entre não definido ( undefined
) e deliberadamente omitido ( null
).
você pode permitir null, defina o propType para não ser obrigatório, uma vez que não é obrigatório: P
@jquense obrigado, isso é super útil! Excluí meu comentário anterior porque essa resposta do SO disse a mesma coisa.
@jquense você pode permitir nulo E indefinido, mas não um ou outro.
Esse é todo o problema! Javascript forneceu essas 2 construções diferentes por uma razão, então forçar todos a tratar null === undefined
para PropTypes é uma limitação artificial.
Só porque eu quero que um PropType permita explicitamente nulo, não significa que eu deva permitir undefined também. São dois casos distintos, e a linguagem os projetou dessa forma propositalmente.
Tenho um PR para contornar esse descuido aqui: https://github.com/facebook/prop-types/pull/90
Eu quero desautorizar undefined
porque isso significa que há um erro de digitação e permitir null
porque isso significa que o chamador passou explicitamente null
. Esse é o ponto desta questão. Eu entendo que este problema está resolvido porque é recomendado apenas alternar para o fluxo, que analisarei.
@binki Uma maneira de permitir null
mas não undefined
é usar sua própria função validadora do PropType.
No exemplo abaixo, apenas null
ou string
são permitidos. A biblioteca PropTypes usa typeof
internamente para verificar se há strings, então fiz o mesmo. Um benefício é que você pode mover essa função para fora do componente e chamá-la quando necessário.
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`)
}
}
Acho que esta solução se desvia da intenção da biblioteca PropTypes - o motivo pelo qual digo isso é devido ao código abaixo da biblioteca PropTypes em https://github.com/facebook/prop-types/blob/master/factoryWithTypeCheckers.js # L189.
Antes de realmente validar, uma verificação rápida é realizada em que as propriedades definidas com isRequired geram automaticamente um erro se o valor da propriedade for null
. Em outras palavras, eles acreditam que uma propriedade obrigatória sendo nula é errônea, enquanto eu considero um caso de uso válido ter valores nulos obrigatórios.
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);
}
Eu concordo com @ jharris4 pelas razões apresentadas. null
não é o mesmo que undefined
. É padrão usá-lo como um espaço reservado.
Da Mozilla Developer Network:
O valor null representa a ausência intencional de qualquer valor de objeto.
null não é um identificador para uma propriedade do objeto global, como pode ser undefined. Em vez disso, null expressa uma falta de identificação, indicando que uma variável não aponta para nenhum objeto. Em APIs, null é geralmente recuperado em um local onde um objeto pode ser esperado, mas nenhum objeto é relevante.
nulo deve ser permitido, pelo menos até PropTypes.oneOfType([null, PropTypes.string]).isRequired
.
@jquense - Remover isRequired
significa que você provavelmente deve definir um padrão. Isso significa que você agora configuraria um padrão para o valor inicial no componente _and_ no redutor, tudo para evitar permitir null
como um valor para um prop?
Eu tenho um monte de data || ''
( isRequired
aceita string vazia ''
, objeto vazio {}
, etc.) em meus seletores porque enquanto aguardo chamadas de API para terminar null
é a coisa perfeita para dizer ao componente que os dados estão chegando, apenas espere um pouco! (mas eu não posso fazer isso ...)
@ puiu91 tem uma boa suspiro
Também concordo que deve haver uma maneira padrão de aceitar null
como valor, pelos mesmos motivos que @ jharris4 e @Findiglay declararam, mas este não é o lugar para continuar a discussão. Este problema não foi apenas encerrado, mas também pertence aos tipos de suporte / facebook . Estou seguindo a solicitação de pull aqui facebook / prop-types # 90.
Ressalto. Ainda estou correndo para isso hoje. Seria ótimo ter suporte integrado para algo como:
myObj: PropType.object.isRequiredOrNull :)
Acho que a prioridade nisso é muito baixa. O fluxo é o caminho recomendado para ir. http://flow.org/
@Marujah seu snippet não está correto.
Tente passar null para o componente e você verá o aviso:
Warning: Failed prop type: The prop 'theProp' is marked as required in 'TheComponent', but its value is null.
O problema é que o isRequired é avaliado PRIMEIRO e nunca permitirá a passagem de valores nulos ou indefinidos.
O PR para os tipos de acessórios para corrigir o problema está no link acima, se você estiver interessado.
Oh, de fato! retestei novamente você está certo
Exigir que um valor ou nulo seja fornecido especificamente deve ser absolutamente permitido por meio de PropTypes.
Aqui está o caso de uso que estou encontrando. Temos alguns retornos de chamada exigidos por 90% de nossos seletores. Os poucos que não precisam deles são casos de uso muito específicos. Temos alguns novos desenvolvedores que estão constantemente se esquecendo de fornecer todos os retornos de chamada usuais.
Eu quero forçar todos os usos desses componentes para tomar a decisão consciente de não incluir callbacks específicos, ao invés de alguém simplesmente esquecer alguns adereços.
Sim, podemos hackear nossas próprias verificações mais específicas por meio do fluxo, mas isso divide nossa validação de props em dois lugares e não é intuitivo para alguém olhando para as definições de propTypes.
Só queria adicionar meu caso de uso aqui. Eu tenho um redux store com dados junto com quando os dados foram buscados, se houve um erro, etc. Meu componente requer um prop 'erro' (para que ele possa exibir o erro para o usuário se os dados não puderem ser buscados), que é nulo quando os dados são carregados com êxito, mas preenchido quando há um erro.
Estou passando um componente do carregador ( PropTypes.node
) como props
, e quando não quero renderizar um carregador, passo null
.
Afaik, uma função render
deve retornar null
vez de undefined
quando não renderizar nada. Portanto, passar null
como o valor parece a maneira correta de fazer isso para mim.
Eu estava implementando o componente InputNumber (wrapper para <input type="number">
), então eu tinha propTypes
para meu prop value
- PropTypes.number.isRequired
, e quando usei meu componente, sempre passou de propriedade. Mas hoje eu preciso passar para lá um link anulável por padrão para valor, e meu componente adiciona um aviso. A única decisão que eu poderia imaginar é mudar propTypes
para minha prop value
para PropTypes.oneOfType([PropTypes.number, PropTypes.string])
e definir defaultProps
como nulo. Mas eu sinto que não é o correto porque o tipo de entrada = número deve funcionar apenas com números.
Estou tentando fazer
PropTypes.oneOfType([null, PropTypes.object]).isRequired
, então nulo ou um objeto, isso não é possível agora?
Ele espera uma função: Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.
Portanto, você deve fornecer uma função, como:
PropTypes.oneOfType([
() => null,
PropTypes.object
]).isRequired
Tendo acabado de encontrar esse bug, escrevi uma função de conveniência para contorná-lo:
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,
};
É possível (mas sem sentido) usar nullable
sem isRequired
. A razão de eu torná-lo compatível com isRequired
é para que funcione com a regra react/require-default-props
eslint.
Meu caso de uso é uma série de componentes em conformidade com uma API comum, envolvida por um único componente que lida com retornos de chamada. null
callbacks significam 'somente leitura', então o componente wrapper às vezes passa intencionalmente null
s. Ao mesmo tempo, é importante que cada propriedade seja passada para os subcomponentes para garantir que, se uma nova propriedade for adicionada, ela não será perdida. Eu também não quero fornecer defaultProps
null para cada componente que está em conformidade com esta API; até onde eles sabem, o chamador deve ter especificado um valor.
Peguei o auxiliar que escrevi antes e coloquei em um pacote junto com um monte de testes para provar a correção:
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,
};
Nova solução: PropTypes.oneOfType([PropTypes.object]).isRequired
Estou recebendo um erro.
como consertar.
AVISO em ./~/prop-types/prop-types.js Dependências críticas: 1: 482-489 Este parece ser um arquivo javascript pré-compilado. Embora isso seja possível, não é recomendado. Tente exigir a fonte original para obter melhores resultados. @ ./~/prop-types/prop-types.js 1: 482-489
Estou tentando fazer
PropTypes.oneOfType([null, PropTypes.object]).isRequired
, então nulo ou um objeto, isso não é possível agora?Ele espera uma função:
Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.
Portanto, você deve fornecer uma função, como:
PropTypes.oneOfType([ () => null, PropTypes.object ]).isRequired
Na verdade eu tive um erro por causa desse 'isRequired' no final, ser nulo e obrigatório ao mesmo tempo não é compatível ...
Isto é o que funcionou para mim:
PropTypes.oneOfType([
PropTypes.string.isRequired,
() => null
])
@ gugol2 observe que o que você escreveu apenas desabilitará completamente a verificação de tipo (agora você pode passar um número para esse prop, ou undefined
, ou qualquer coisa); a função que você fornece deve retornar null
se a validação for bem-sucedida e não null
se falhar.
Se você deseja seguir esse caminho, você precisa de algo mais como:
PropTypes.oneOfType([
PropTypes.string.isRequired,
(props, key) => props[key] === null ? null : 'Not null'
])
Claro que você pode predefinir a função auxiliar de aparência desagradável:
const nullable = (props, key) => props[key] === null ? null : 'Not null'
// ...
PropTypes.oneOfType([PropTypes.string.isRequired, nullable])
Também é estranhamente possível (mas eu realmente não recomendo!) Usar apenas PropTypes.oneOfType([PropTypes.string.isRequired])
. Isso parece um bug e eu não esperaria que um código como esse sobrevivesse às versões posteriores. Observe também que é semelhante, mas não igual, a um método sugerido anteriormente que não funciona.
Se você puder esperar, há um PR aberto que está se movendo incrivelmente devagar, mas aparentemente ainda está em consideração.
E até que o PR seja mesclado, eu recomendo usar o pacote que criei (ou o código por trás dele ) porque dessa forma você coloca .isRequired
no final da linha, o que o torna compatível com as regras de linting.
IMHO este é um comportamento correto, mas deve ser documentado.
Um caso de uso comum que vejo é o React renderizando um componente antes que uma chamada de API para dados seja concluída. A primeira renderização renderia, por exemplo, uma lista de itens (
items: null
). Em seguida, a chamada API termina e agoraitems
é preenchido com uma matriz.
Alguma melhor maneira de lidar com isso? Eu quero que esse suporte seja obrigatório, MAS ele é nulo antes de eu recuperá-lo da API.
PropTypes.oneOfType([ PropTypes.string.isRequired, (props, key) => props[key] === null ? null : 'Not null' ])
@ davidje13 Eu encontro um pequeno problema com essa abordagem. O teste de cobertura tem 1/4 de caso que nunca é coberto.
Digamos que eu tenha um Login de componente que tem apenas um 'nome' de prop que pode ser nulo ou uma string necessária:
const Login = ({name}) => {
return <div>{name}</div>
}
Portanto, seus proptypes são:
Login.propTypes = {
name: PropTypes.oneOfType([
PropTypes.string.isRequired,
(props, key) => (props[key] === null ? null : 'Not null'),
]),
};
Quando eu testo este componente, eu realmente tenho apenas 2 cenários, null OU uma string necessária.
render(<Login name={null} />
render(<Login name={'anyName'} />
Mas a cobertura me diz que meu teste tem apenas 75% de cobertura.
Eu me pergunto qual será a abordagem oficial para isso.
Parece que seu caso de teste ausente é aquele em que falha na verificação de suporte? ou seja, se você passar um número ou indefinido ou outra coisa que não deveria.
Parece que seu caso de teste ausente é aquele em que falha na verificação de suporte? ou seja, se você passar um número ou indefinido ou outra coisa que não deveria.
Não, não é isso.
Passar por indefinido não expande a cobertura.
E não posso passar um número de qualquer maneira, não é um valor permitido.
Não sou capaz de cobrir esse caso.
Comentários muito úteis
Um caso de uso comum que vejo é o React renderizando um componente antes que uma chamada de API para dados seja concluída. A primeira renderização renderia, por exemplo, uma lista de itens (
items: null
). Em seguida, a chamada API termina e agoraitems
é preenchido com uma matriz.