Предупреждение: flattenChildren (...): обнаружены два ребенка с одним и тем же ключом/дочерние ключи должны быть уникальными

Вчера я добавил react-router-dom в свой проект, и теперь, когда я ухожу и возвращаюсь к элементу Sky в моем навигаторе, он перезагружает небо, и я получаю

Предупреждение: flattenChildren (...): Обнаружены два ребенка с одним и тем же ключом, element-id-50. Детские ключи должны быть уникальными; когда у двух детей есть ключ, будет использоваться только первый ребенок.

(номер 50, использованный выше, является просто примером, он выдает эту ошибку ~ 40 раз каждый раз с разными идентификаторами)

Проблема, похоже, проистекает из моего файла sky.js:

componentWillMount() {
    this.props.dispatch(requestSkySetup());
    this.props.dispatch(requestAllElements());

    this.setState({loadedSky: true, loadedElements: true});
}

Поскольку каждый раз, когда я иду на другой экран, этот компонент размонтируется, а затем снова монтируется, когда я возвращаюсь.

Когда receiveSkySetup завершено, функция render в sky.js создает кучу divs под названием Sector, и каждый Sector создает несколько divs под названием Slot s.

Тогда внутри Slot.render у меня есть:

return connectDropTarget(
            <div className={showOutline ? 'slot showOutline' : 'slot'} style={style} onClick={interactable ? this.handleClick : null}>
                {
                    elements
                        .map(e => (
                            <SkyElement
                                id={e.id}
                                key={`element-id-${e.id}`}
                                title={e.title}
                                size={150}
                                opacity={e.opacity}
                                glow={e.glow}
                                color={e.color}
                                sectorId={e.sectorId}
                                slotId={e.id}
                                dispatch={this.props.dispatch}
                                isDragging={false}
                                transformElement={false} />
                        ))
                }
            </div>
        );

Элемент key в вызове SkyElement выше - это то, что бросает 40+ ошибок на каждом монтаже.

С удовольствием предоставим больше кода при необходимости.

Любая помощь будет чрезвычайно полезна. Спасибо!

Изменить: элементы ведения журнала консоли

Копаясь немного больше, предметы удваиваются в моем магазине.

Итак, на втором рендере вкладки Sky полный список идентификаторов элементов ["0", "1", "2", "3", "4", "5", "6", "7", "17", "18", "19", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "77", "78", "0", "1", "2", "3", "4", "5", "6", "7", "17", "18", "19", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "77", "78"]

На третьем рендере элементы 0-78 (иды, которые применяются из массива выше) будут добавлены снова в массив

В Slot.js

const mapStateToProps = ({elements}, ownProps) => {
    return {
        elements: getElementsBySlotId(elements, ownProps.id),
    };
};

elements здесь будет n умножить на количество нагрузок, сделанных Sky.

В sky.js

const mapStateToProps = ({sky, elements}) => {
    return {
        sectors: getSky(sky).sectors,
        elements: getElementsByKeyName(elements, 'visibleElements'),
        unplacedElements: getElementsByKeyName(elements, 'unplacedElements'),
    };
};

Печать elements.length Я вижу, что они тоже здесь удваиваются. Slot.js вытаскивает из одного и того же хранилища, поэтому имеет смысл

В моем elements/reducer.js

case 'receiveAllElements':
        const visibleElements = {};
        const unplacedElements = {};

        const elements = action.elements.reduce((result, index) => {
            result[`${index.id}`] = index;
            return result;
        }, {});

        const keys = Object.keys(elements);
        for (const key of keys) {
            const e = elements[key];

            if (e.sectorId === null) {
                unplacedElements[key] = e;
            } else {
                visibleElements[key] = e;
            }
        }

        const visibleIds = Object.keys(visibleElements);
        const unplacedIds = Object.keys(unplacedElements);
        console.log(visibleIds);
        console.log(unplacedIds); // logging these, the numbers are consistent and don't double, triple etc with each load

        return {
            ...state,
            elementsMap: {
                ...state.elementsMap,
                ...elements,
            },
            visibleElements: [...state.visibleElements, ...visibleIds],
            unplacedElements: [...state.unplacedElements, ...unplacedIds],
        };

Может быть, что-то там вызывает удвоение счета?

Ответы

Ответ 1

Проблема здесь была

    return {
        ...state,
        elementsMap: {
            ...state.elementsMap,
            ...elements,
        },
        visibleElements: [...state.visibleElements, ...visibleIds],
        unplacedElements: [...state.unplacedElements, ...unplacedIds],
    };

а именно значения visibleElementsunplacedElements).

[...state.visibleElements, ...visibleIds] будет concat 2 массивов, так как этот код попадал каждый раз, когда я возвращался на вкладку Sky, он добавлял новые идентификаторы в ...visibleIds к массиву, который у меня уже был в ...state.visibleElements и значения удвоения