Безопасно ли настраивать / переопределять части стороннего компонента React с помощью extend? (Игнорировать «композицию над наследованием» ПРОТИВ изменения исходного кода?)

#javascript #reactjs #inheritance #primereact

Вопрос:

Я работаю с этим выпадающим списком третьей стороны — primereact — и это компонент primereact/multiselect … Мне нужно, чтобы все работало в точности так, как написал первоначальный разработчик, за исключением нескольких функций. Эти функции недоступны с помощью реквизита. Мне интересно, есть ли способ «наилучшей практики». Проблема с исходным кодом-в флажке «Выбрать все» есть ошибка, и я хочу изменить функцию значка «Закрыть»; в моем приложении она избыточна.

Это единственные два варианта, которые я мог придумать:

  1. Скопируйте весь исходный код элемента третьей стороны, измените его напрямую, а затем удалите зависимость. Хотя мне кажется, что это похоже на воровство.
  2. Расширьте компонент и переопределите функции

Вот сторонний исходный код: https://bit.dev/primefaces/primereact/multiselect/~code#multiselect/MultiSelect.js

и вот мой код:

 import React from 'react';
import { MultiSelect } from 'primereact/multiselect';
import {customMultiSelectSearchHeader} from './searchSafeMultiSelect.css';

class SearchSafeMultiSelect extends MultiSelect {
    constructor(props) {
        super(props);
        this.state = { 
            filter: ''
        };
        // Binds certain functions to NEW class, instead of __proto__
        this.hasFilter = this.hasFilter.bind(this);
        this.onClick = this.onClick.bind(this);
        this.onOptionClick = this.onOptionClick.bind(this);
        this.onOptionKeyDown = this.onOptionKeyDown.bind(this);
        this.onFocus = this.onFocus.bind(this);
        this.onBlur = this.onBlur.bind(this);
        this.onFilter = this.onFilter.bind(this);
        this.onCloseClick = this.onCloseClick.bind(this);
        this.onToggleAll = this.onToggleAll.bind(this);
    }
    
    // Changes icon next to search bar from X to trash can. 
    originalRenderHeader = this.renderHeader;
    renderHeader = (items) => {
        const header = this.originalRenderHeader(items);
        return (
            <div className={customMultiSelectSearchHeader}>
                {header}
            </div>
        );
    }

    // Makes clicking the Trash (previously X) icon close the dropdown AND clear selection.
    onCloseClick = (event) => {
        this.hide();
        this.updateModel(event.originalEvent, []);
        event.preventDefault();
        event.stopPropagation();
    }

    // Fixes bug in dependency - ALL box is checked if all visible options are selected.
    isAllChecked = (visibleOptions) => {
        if(this.hasFilter()) {
            return this.props.value amp;amp; visibleOptions amp;amp; visibleOptions.length 
            amp;amp; this.filterOptions(this.props.options).find(visible => this.props.value.indexOf(this.getOptionValue(visible) == -1) == undefined;
        }
        else {
            return this.props.value amp;amp; this.props.options amp;amp; (this.props.value.length === this.props.options.length);
        }
    }
}


export default SearchSafeMultiSelect;
 

Файл CSS ./searchSafeMultiSelect.css:

 .customMultiSelectSearchHeader button span::before{
    content: "e93d" !important;
}
 

package.json (устанавливает версию primereact ровно на 5.0.1, если они обновятся, мой код должен остаться прежним)

     "primereact": "5.0.1",
 

Это работает так, как и ожидалось. Мне просто интересно, не делаю ли я здесь что-то запретное. Я просмотрел множество руководств, но не видел, чтобы кто-либо в Интернете изменял зависимости таким образом. Это заставляет меня сомневаться в том, безопасен ли мой подход.

Правка: Да, я много читал здесь о «Композиции над наследованием», но в случае сторонних компонентов единственный способ изменить состав базы-это напрямую изменить исходный код зависимости. Итак, я чувствую, что застрял между 2 плохими вариантами-изменением исходного кода или использованием наследования.

Комментарии:

1. Если это действительно ошибка: 1) сообщите о проблеме 2) разветвите проект 3) исправьте ошибку в своем форке 4) измените свою зависимость, чтобы использовать свой форк 5) отправьте запрос на удаление с просьбой объединить ваши изменения в проект. https://github.com/primefaces/primereact/

2. Одна из проблем-ошибка, но есть и вторая модификация, относящаяся к конкретному проекту. Я попытаюсь подтолкнуть к большому исправлению в самом primereact, но у меня все еще есть дилемма со второй модификацией.

3. Вы могли бы сделать второй мод в другой развилке. Я не знаю ни одной технической причины, по которой вы не можете расширить компонент, но это немного похоже на запах кода , и я бы тщательно подумал, прежде чем идти по этому пути. Команда React даже не советует этого делать. (Я понимаю, что это осложняется тем фактом, что базовый компонент является сторонним, но все же.)

4. Да, это хороший довод. Оказывается, ошибки даже были исправлены в обновлении, поэтому я закрыл проблему. Упс! К сожалению, исправленная версия несовместима с другими элементами моего приложения. Итак, что я сделаю-если я смогу опубликовать вилку в системе Git моей организации, я буду использовать пользовательский пакет. В противном случае я скопирую/отредактирую необходимый компонент.. Копирование компонента теперь имеет больше смысла, так как необходимая нам версия устарела. Я бы предпочел иметь копию в приложении, чтобы никто в будущем не пытался обновлять. Я бы связал оригинал в комментариях к коду, тхо! Спасибо за советы.