这个问题可能更多是关于见解,而不是事实,但是我不确定我是否会问。
我正在构建一些将显示数据并允许进行编辑的表格,字段数据来自props(因为父组件正在使用GraphQL查询来提取更大的数量并传递给每个孩子)。
我发现一些输入数据正在评估为null(因为它没有从查询中传回),这会引发警告,因为输入不喜欢被分配为null值。
我的问题是,传递这些值时,对每个变量进行检查并在需要时分配空字符串的最干净方法是什么?
到目前为止,我尝试过的两个选项是:
有条件地将每个对象分配给状态对象,但这感觉很笨拙,并且代码很多:
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);
}, [] )
老实说,这感觉比第一种方法更干净,但是会在很多地方发生这种情况,因此必须在每种情况下都这样做会产生反作用。
任何帮助/见解表示赞赏。
答案 0 :(得分:1)
编辑: 。事实证明,OP为此使用了材料UI。意味着,输入显示警告的原因是由于使用PropTypes的材料UI。我建议OP为<Input />
组件创建一个包装器,并传递所有道具。在包装器组件内部,您可以执行以下操作:<InputWrapper value={props.value || ""} {...rest} />
,其中涵盖了所有内容。
InputWrapper:
import React from 'react';
import { Input } from '@material-ui/core';
export default function InputWrapper({ value, ...rest }) {
return <Input value={value || ""} {...rest} />
}
正在使用InputWrapper:
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')
);
原始答案:
您的用例是什么?没有理由运行检查并分配空字符串...
如果您要强制使用某些属性,请查看PropTypes ...如果您不想强制使用某些道具,我建议您在使用时检查一个值变量。即使最初将其设置为空字符串,您仍然可能会遇到一些错误-我不明白您从空字符串中获得了什么。
我不了解用例-您能否详细说明为什么需要将其设置为空字符串?
如果您确实愿意,可以验证:useState({two: props.two || ""})
...但是仍然没有必要。
// Notice how prop "two" is not being used..
function Test(props) {
const [state, setState] = React.useState({
one: props.one,
two: props.two
})
return(
<div>
<p>{state.one}</p>
<p>Even though <code>state.two</code> does not exist, there are no errors.. (at least for this demonstration)</p>
<input type="text" value={state.two} />
<input type="text" value={state.two} defaultValue={"default"} />
<p><i>If you really wanted to, you could verify like:</i><code>useState({two: props.two || ""})</code><i>...but it is still unnecessary..</i></p>
</div>
);
}
ReactDOM.render(<Test one="I AM ONE" />, document.body)
code {
margin: 0 10px;
padding: 3px;
color: red;
background-color: lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
答案 1 :(得分:0)
制作方法KickOutNullValues()可以做什么,然后可以在需要的地方重复使用。那会更优雅。
答案 2 :(得分:0)
这是一个棘手的问题,我不知道正确的答案。您已经尝试了两种方法,通常我会做的另一种方法是
如果您只是想正确显示,我会做
<Telephone data={props.telephone} />,
const Telephone = ({data}) => { if (!data) return null }
我发现这是为了允许子组件确保此问题的有效性,而不是在父API级别中整理数据。
Telephone.defaultProps = {
data: ''
}
这进一步确保了如果数据为空,则defaultProps
我大多数时候喜欢这种方式的原因是,我真的不想弄乱API数据的来源TRUTH。
当然,如果您确实想确保数据始终有效,则可能会更好:)
答案 3 :(得分:0)
如果将原始算法放入回调中,您的代码将开始具有类似意大利面条的品质。我建议在外面写一个function
。
您对Array#map
的使用是不正确的,或者您正在以一种意想不到的方式使用它。 Array#map
用于构造一个全新的数组。您正在模拟Array#forEach
。另外,您正在执行假条件检查。 null
是JavaScript中被视为false
的众多值之一。即,您的痛点可能是undefined
,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_arr
的变量是一个对象,这很具有欺骗性。
答案 4 :(得分:0)
您不应在地图上使用钥匙。
考虑一下:(类似于您的)
useEffect(() => {
let state_arr = Object.keys(props).map(prop => prop ? {prop} : { prop: '' });
setState(state_arr);
}, [])
通过使用此代码,您可以创建带有对象的数组,并且可以轻松访问每个项目
如果没有昵称,它将看起来像这样:
[{ telephone: '245-4225-288' }, { nickname: '' }]
你怎么看?