Javascript 什么';这是确保没有空值的最佳方法

Javascript 什么';这是确保没有空值的最佳方法,javascript,reactjs,Javascript,Reactjs,这个问题可能更多的是关于观点而不是事实,但我不确定,所以我想我会问 我正在构建一些表单,这些表单将显示数据并允许编辑,字段数据来自props(因为父组件正在使用GraphQL查询来提取更大的数据量并传递给每个子组件) 我发现一些输入数据的计算结果为null(因为它不是从查询中传回的),这会引发一个警告,因为输入不喜欢被分配null值 我的问题是,当传递这些值时,对每个变量运行检查并在需要时分配空字符串的最干净的方法是什么 到目前为止,我尝试过的两种选择是: 有条件地将每个对象指定给state对象

这个问题可能更多的是关于观点而不是事实,但我不确定,所以我想我会问

我正在构建一些表单,这些表单将显示数据并允许编辑,字段数据来自props(因为父组件正在使用GraphQL查询来提取更大的数据量并传递给每个子组件)

我发现一些输入数据的计算结果为null(因为它不是从查询中传回的),这会引发一个警告,因为输入不喜欢被分配null值

我的问题是,当传递这些值时,对每个变量运行检查并在需要时分配空字符串的最干净的方法是什么

到目前为止,我尝试过的两种选择是:

有条件地将每个对象指定给state对象,但这感觉很笨拙,而且代码很多:

const [state, setState] = useState({
    telephone: props.telephone ? props.telephone : '',
    nickname: props.nickname ? props.nickname : ''
    etc...
});
或在设置状态之前定义映射到道具并检查值的函数:

useEffect( () => {
    let state_arr = {};
    Object.keys(props).map( (key) => {
        if( !props[key] ) state_arr[key] = '';
        else state_arr[key] = props[key];
    } );
    setState(state_arr);
}, [] )
老实说,这感觉比第一种选择更干净,但是有很多地方会发生这种情况,而且在每种情况下都必须这样做会适得其反


非常感谢您的帮助/见解。

制作KickOutNullValues()方法怎么样?该方法可以满足您的需要,然后您可以在任何需要的地方重用它。那会更优雅

这是一个很难回答的问题,我不知道正确的答案。你已经试过两种方法了我通常的不同方法是

如果你只是想把显示器弄对,我就这么做

   <Telephone data={props.telephone} />,
   const Telephone = ({data}) => { if (!data) return null }
这进一步确保了如果数据为空,则将由
defaultProps将其重置为“”

大多数时候我喜欢这种方式的原因是我不想弄乱API数据的原始真相

当然,如果您确实希望确保数据始终有效,您的方法可能会更好:)

编辑:结果是OP为此使用了材质UI。这意味着,输入显示警告的原因是材质UI使用了PropTypes。我建议OP为
组件创建一个包装器,并传递所有道具。在包装器组件内部,您只需执行以下操作:
,这包括了一些内容

输入包装器:

import React from 'react';
import { Input } from '@material-ui/core';

export default function InputWrapper({ value, ...rest }) {
  return <Input value={value || ""} {...rest} />
}
import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';
import InputWrapper from './InputWrapper.js';


function App(props) {
  const [state, setState] = useState({});

  useEffect(() => {
    setState({
      name: props.name,
      age: props.age,
      hairColor: props.hairColor,
    })
  }, [props.name, props.age, props.hairColor]);

  const handleChange = (event, inputType) => {
    setState({...state, [inputType]: event.target.value})
  }

  return(
    <div>
      {/* Shows that you can pass through native <Input /> props: */}
      {/* state.name is null here! Warning is NOT thrown in the console! */}
      <InputWrapper value={state.name} fullWidth onChange={e => setState({...state, name: e.target.value})} />
      <InputWrapper value={state.name} multiline onChange={e => setState({...state, name: e.target.value})} />

      {Object.keys(state).map((item, index) => {
        return (
          <div>
            <InputWrapper 
              key={`${item}_${index}`} 
              value={state[item]} 
              onChange={e => handleChange(e, item)} />
          </div>
        );
      })}
    </div>
  );
}

render(
  <App name={null} age={44} hairColor="blue" />, 
  document.getElementById('root')
);
code{
利润率:0.10px;
填充:3倍;
颜色:红色;
背景颜色:浅灰色;
}

如果将原始算法放入回调函数中,代码将开始具有意大利面条般的特性。我建议在外部编写
函数

您对
Array#map
的使用不正确,或者更确切地说,您是在以一种非预期的方式使用它
Array#map
用于构建一个全新的数组。您正在模拟
阵列#forEach
。此外,您正在执行错误的条件检查
null
是JavaScript中被视为
false
的许多值之一。也就是说,您的痛点可能是
未定义
0
,以及
'
。如果唯一的无效返回值是
null
,则显式检查
null

用于预期用例的可枚举项是
Array#reduce

function nullValueReplacer(obj) {
  return Object.entries(obj).reduce((newStateArr, [currentKey, currentValue]) => {
    if (currentValue === null) {
      newStateArr[currentKey] = ''
    } else {
      newStateArr[currentKey] = currentValue
    }
    return newStateArr
  }, {});
}
作为补充说明,您可能需要更新变量名。你有一个叫做
state\u arr
的变量,它是一个对象,这是非常具有欺骗性的。

对象数组-小修正 您不应将密钥用于映射

想想这个:(和你的一样)

通过使用此代码,您可以使用object创建一个数组,并且可以轻松访问每个项目

如果没有昵称,它将如下所示:

[{电话:'245-4225-288'},{昵称:'}]


您认为呢?

这种方法不需要为每个输入创建一个常量吗?我喜欢这个想法,但是在一个有20个输入的表单中这样做可能是一个噩梦。这是真的,如果你需要确保这个对象从一开始就存在,那么是的。你是对的,例如通过
redux
。我只是试图从显示的角度来解决这个问题。我通常不在乎对象引用在大多数情况下是否会通过
React.Memo更改。我还想添加的是,如果您将某个对象从
null
更改为某个对象,例如
onChange
。你总是会得到一个新的对象。因此,从这个角度来看,也许你的方法是唯一的:)将null值分配给输入会引发警告,“
input
上的value`prop不应该为null”-我正在运行这些检查来解决这个问题,是的,将每一个状态分配为
useState({two:props.two | | |“})
是一个选项,但是,对于包含15-20个输入的表单来说,这并不完全是干净的。现在,我们正在取得进展!您正在将道具传递给
输入
字段。。在我看来,处理这个问题的最好方法是使用要求使用这些道具。。。orrrr您是否尝试过在输入上使用
defaultValue={”“}
prop?此外,在
中提供空变量时,我没有收到任何警告或错误。。。我已经更新了答案以反映这一点…(控制台中没有错误或警告)…@MattOestreich虽然推荐道具类型是个好主意,但它们不会解决OP的问题(某些值为null)-它只会在运行时警告他它们为null,他已经知道了,我在做这个项目的时候为其他组件做了这么多包装,真不敢相信我没有想到要做这么简单的事情!谢谢,伙计,工作得很好!如果我误解了,很抱歉-但是我在迭代道具,道具是不可变的,构建一个新的数组不是预期的行为吗?@AdamRoberts
array#reduce
创建一个新实体。当你使用道具时,你不是在变异道具。我使用的算法在功能上与您在第二个代码块中使用的算法相同。我知道
reduce
创建了一个新实体,但是在
map
上使用
reduce
有什么好处呢。在这两种情况下,我都需要创建一个新数组并将其分配给s
function nullValueReplacer(obj) {
  return Object.entries(obj).reduce((newStateArr, [currentKey, currentValue]) => {
    if (currentValue === null) {
      newStateArr[currentKey] = ''
    } else {
      newStateArr[currentKey] = currentValue
    }
    return newStateArr
  }, {});
}
useEffect(() => {
  let state_arr = Object.keys(props).map(prop =>  prop ? {prop} : { prop: '' });
  setState(state_arr);
}, [])