Javier
Javier

Reputation: 2105

How can detect that should update a property of previous object?

First of all, give thanks for reading my question and try to help me and apologize for my English.

I'm trying to create a method on Redux using React that change visibility of a layer.

My problem is that change visibility perfect but when all layers are no visibles and try to change them to visibles their before property is undefined, except last one that changes.

I'm going to explain me better with an example.

mapLayers is an array that contains 3 layers:

  • [2] Layer3
  • 1 Layer2
  • [0] Layer1

CASE 1:

If I hide Layer1 his before property is undefined, and now I show Layer1 and now his before property is id of Layer2.

MY PROBLEM:

  • [2] Layer3
  • 1 Layer2
  • [0] Layer1

3 Layers are no visibles, so:

  1. Change Layer2 to visible -> before = undefined
  2. Change Layer3 to visible -> before = undefined
  3. Change Layer1 to visible -> before = id of Layer2

But when change Layer3 to visible (on step 2), before should be undefined and later, when chage visibility of Layer2.. before of Layer3 should be Layer2 id.

Is important know that I'm using react-mapbox-gl, and I need before property to move and hido/show layers.

before: string Pass the id of a layer, it will display the current layer before the layer defined by the id.

https://github.com/alex3165/react-mapbox-gl/blob/master/docs/API.md

Here is my code:

static changeLayerVisibility(layer) {
    let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
    const ids = mapLayers.map(l => l.id);
    const index = ids.indexOf(layer.id);
    const newVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';

    let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout.visibility === 'visible');

    let updateLayout = Object.assign({}, mapLayers[index], {
        layout: Object.assign({}, mapLayers[index].layout, { visibility: newVisibility }),
        paint: Object.assign({}, mapLayers[index].paint),
        before: newVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined
    });

    mapLayers.splice(index, 1, updateLayout);

    return (dispatch) => {
        dispatch({
            type: MapTypeConstants.SET_MAP_LAYERS,
            payload: mapLayers
        });
    };
}

Upvotes: 0

Views: 98

Answers (2)

Javier
Javier

Reputation: 2105

SOLUTION:

Thanks a lot for your help and ideas but I've solved it like this.

In Redux I've created a new method to update before property when layer has change his visibility and is undefined when should be the id of next layer.

And, Is not possible update that layer inside changeVisibility because, the layer that change the visibility should be drawn (rendered). If is not drawn, the application crash because property before has the id of next layer and next layer is not drawn yet.

REDUX:

static changeLayerVisibility(layer) {

    let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
    const ids = mapLayers.map(l => l.id);
    const index = ids.indexOf(layer.id);
    const layoutVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';

    let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout && layerObj.layout.visibility && layerObj.layout.visibility === 'visible');
    let updateLayout = Object.assign({}, mapLayers[index], {
        layout: Object.assign({}, mapLayers[index].layout, { visibility: layoutVisibility }),
        paint: Object.assign({}, mapLayers[index].paint),
        filter: (mapLayers[index].filter) ? Object.assign({}, mapLayers[index].filter) : {},
        before: layoutVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined,
        visible: (layoutVisibility === 'visible') ? true : false
    });
    if (this.updateLayout.type === 'raster') delete updateLayout.filter;

    mapLayers.splice(index, 1, updateLayout);

    return (dispatch) => {
        dispatch({
            type: MapTypeConstants.SET_MAP_LAYERS,
            payload: mapLayers
        });
    };
}


static updateBefore(layer) {

    let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
    const ids = mapLayers.map(l => l.id);
    const posInRedux = ids.indexOf(layer.id);

    let updateBeforeLayout = Object.assign({}, layer, {
        layout: Object.assign({}, layer.layout),
        paint: Object.assign({}, layer.paint),
        filter: (layer.filter) ? Object.assign({}, layer.filter) : {},
        before: (mapLayers[posInRedux + 1]) ? String(mapLayers[posInRedux + 1].id) : undefined,
        visible: layer.visible
    });
    if (this.updateBeforeLayout.type === 'raster') delete updateBeforeLayout.filter;

    mapLayers.splice(posInRedux, 1, updateBeforeLayout);

    return (dispatch) => {
        dispatch({
            type: MapTypeConstants.SET_MAP_LAYERS,
            payload: mapLayers
        });
    };
}

FRONT-END:

changeVisibility(layer) {
    this.props.changeLayerVisibility(layer);
    let layerBeforeUndefined = this.props.mapGLlayers.find(l => l.visible === true && l.before === undefined);
    if (layerBeforeUndefined) {
        setTimeout( () => {
            this.props.updateBefore(layerBeforeUndefined);
        });
    }
};

Now, I want reduce code in front because all logic it has to be one redux and it has to look like this:

changeVisibility(layer) {
    let userMapboxLayers = this.props.map.getStyle().layers.filter(l => l.source && l.source.indexOf('sourceId_') !== -1);
    this.props.changeLayerVisibility(userMapboxLayers, layer);
};

Upvotes: 0

Root
Root

Reputation: 2361

Actually,I think there is a better ways to set your properties.


First,use an Array to store visibility properties.Like the below, and the initial value should be false.

interface InVisiablityProps {
   visible: Array<Boolean>
}

const initialState:InVisiablityProps = {
   invisible: [false,false,false]
}

Every change the view to invisible.change the property to !(property)

Upvotes: 1

Related Questions