如何处理react.js中缺少的字段

时间:2014-10-26 18:59:15

标签: javascript json rest design-patterns reactjs

我们假设有一个用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相关的结构。

感谢您的帮助!

2 个答案:

答案 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响应,但是)。

相关问题