src/reducers/map.js
function addFeatures(state, action) {
  const source = state.sources[action.sourceName];
  if (!source) {
    return state;
  }
  const data = source.data;

  // placeholder for the new data
  let new_data = null;
  let features;
  if (action.features.features) {
    // When a full geoJson object is passed in, check the projection
    features = reprojectGeoJson(action.features);
  } else {
    // Pass along an just features
    features = action.features;
  }

  // when there is no data, use the data
  // from the action.
  if (!data || !data.type) {
    // coerce this to a FeatureCollection.
    new_data = {
      type: 'FeatureCollection',
      features,
    };
  } else if (data.type === 'Feature') {
    new_data = {
      type: 'FeatureCollection',
      features: [data].concat(features),
    };
  } else if (data.type === 'FeatureCollection') {
    let featureCollection = [];

    if (action.position > -1) {
      for (let i = 0, ii = data.features.length; i < ii; i++) {
        if (i === action.position) {
          for (let x = 0, xx = features.length; x < xx; x++) {
            featureCollection.push(features[x]);
          }
        }
        featureCollection.push(data.features[i]);
      }
    } else {
      featureCollection = data.features.concat(features);
    }
    new_data = Object.assign({}, data, {features: featureCollection});
  }

  if (new_data !== null) {
    return changeData(state, action.sourceName, new_data);
  }
  return state;
}
function addFeatures(state, action) {
  const source = state.sources[action.sourceName];
  if (!source) {
    return state;
  }
  const data = source.data;

  // placeholder for the new data
  let new_data = null;
  let features;
  if (action.features.features) {
    // When a full geoJson object is passed in, check the projection
    features = reprojectGeoJson(action.features);
  } else {
    // Pass along an just features
    features = action.features;
  }

  // when there is no data, use the data
  // from the action.
  if (!data || !data.type) {
    // coerce this to a FeatureCollection.
    new_data = {
      type: 'FeatureCollection',
      features,
    };
  } else if (data.type === 'Feature') {
    new_data = {
      type: 'FeatureCollection',
      features: [data].concat(features),
    };
  } else if (data.type === 'FeatureCollection') {
    let featureCollection = [];

    if (action.position > -1) {
      for (let i = 0, ii = data.features.length; i < ii; i++) {
        if (i === action.position) {
          for (let x = 0, xx = features.length; x < xx; x++) {
            featureCollection.push(features[x]);
          }
        }
        featureCollection.push(data.features[i]);
      }
    } else {
      featureCollection = data.features.concat(features);
    }
    new_data = Object.assign({}, data, {features: featureCollection});
  }

  if (new_data !== null) {
    return changeData(state, action.sourceName, new_data);
  }
  return state;
}
Add features to a source.
@param {Object} state Current state.
@param {Object} action Action to handle.

@returns {Object} The new state.