我们假设有一个用react.js编写的应用程序。它通过rest api获取单个json并将一些属性传递给子组件。
处理json和东西可能缺少的属性的正确方法是什么?我可能应该检查每个组件是否有道具,并填充状态与适当的结构,但填充空数据,如下所示:
var SomeComponent = React.createClass({
getInitialState: function() {
return {
someNestedStructure: {
foo: {
bar: null,
baz: null
},
morenested: {
something: '',
andEvenMoreNested: {
somethingb: ''
}
},
somedata: {
id: null
},
somedataaa: {
}
}
}
},
componentDidMount: function() {
//call rest api and set new state depending on what is inside json
//check every required field to pass to children compoents
},
render: function() {
return (
<div>
<ComponentUsingNEsteStructure data={this.state.someNestedStructure.moreNested}/>
<ComponentThatNeedsEverythign data={this.state.someNestedStructure} />
<SomeOtherComponent some={this.sate.somedataaa} />
</div>
);
}
});
但我猜它会在代码和很多ifs中生成很多与json相关的结构。
感谢您的帮助!
答案 0 :(得分:2)
这不是React特有的。你想要的是深度延伸。这在npm作为deep-extend
提供用法如下:
var defaultsForThing = {
foo: '',
bar: {
baz: true,
quux: null
}
};
// make a defaulting function
var defaultThing = deepExtend.bind(null, defaultsForThing);
// fetch some data which might be missing fields
$.getJSON('/api', function(data){
var fixed = defaultThing(data);
doSomethingWith(fixed);
});
这是deepExtend函数(但更喜欢linked to module)
var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) {
if (arguments.length < 1 || typeof arguments[0] !== 'object') {
return false;
}
if (arguments.length < 2) return arguments[0];
var target = arguments[0];
// convert arguments to array and cut off target object
var args = Array.prototype.slice.call(arguments, 1);
var key, val, src, clone, tmpBuf;
args.forEach(function (obj) {
if (typeof obj !== 'object') return;
for (key in obj) {
if ( ! (key in obj)) continue;
src = target[key];
val = obj[key];
if (val === target) continue;
if (typeof val !== 'object' || val === null) {
target[key] = val;
continue;
} else if (val instanceof Buffer) {
tmpBuf = new Buffer(val.length);
val.copy(tmpBuf);
target[key] = tmpBuf;
continue;
} else if (val instanceof Date) {
target[key] = new Date(val.getTime());
continue;
} else if (val instanceof RegExp) {
target[key] = new RegExp(val);
continue;
}
if (typeof src !== 'object' || src === null) {
clone = (Array.isArray(val)) ? [] : {};
target[key] = deepExtend(clone, val);
continue;
}
if (Array.isArray(val)) {
clone = (Array.isArray(src)) ? src : [];
} else {
clone = (!Array.isArray(src)) ? src : {};
}
target[key] = deepExtend(clone, val);
}
});
return target;
}
我可能在这个功能中改变的一点是它不能很好地满足这个案例:
var defaults = {
a: [{b: 0, c: 0}]
};
var obj = {
a: [{b: 1}, {b: 2}, {c: 3}]
};
deepExtend(defaults, obj);
为了修复json响应,你最终会想到以下内容,但这在技术上并不是一个深层默认值(它的架构强制)。
{
a: [{b: 1, c: 0}, {b: 2, c: 0}, {c: 3, b: 0}]
}
答案 1 :(得分:0)
您可以使用getDefaultProps为每个组件的道具指定默认值以避免缺少值,从而避免顶层的大型嵌套对象。您可以将REST API访问权限移动到父项,并通过其道具将结果传递给子项(您必须使用父状态作为触发器来重新呈现子项以获取AJAX响应,但是)。