如何处理react.js中丢失的字段

How to deal with missing fields in react.js

本文关键字:字段 js react 何处理 处理      更新时间:2023-09-26

让我们假设有一个用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>
  );
}
});

但我想它在代码中生成了很多与json相关的结构和很多if。

谢谢你的帮助!

这不是React特有的。你想要的是深度延伸。这在npm上可用作深度扩展

用法如下:

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功能(但更喜欢链接到模块)

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}]
}

您可以通过使用getDefaultProps为每个组件的props分配默认值来满足缺少值的需求,从而避免在顶级使用大型嵌套对象。您可以将REST API访问移动到父级,并通过子级的道具将结果传递给子级(不过,在获得AJAX响应时,您必须使用父级的状态作为触发器来重新提交子级)。