• Почему при обновлении стейта родителя дочка ререндерится вместо обновления?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Ещё интереснее, я начал сетстейтать, закидывая в функцию вместо колбэка готовый новый объект. why did you render перестал сообщать о ре-рендере, но логи компонента маркетплейса - первый таб настроек - всё равно говорят о том, что компонент ре-рендерится каждый раз при сетстейте в родителе
  • Почему при обновлении стейта родителя дочка ререндерится вместо обновления?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    camelCaseVlad Значит я просто не понимаю как сетстейтить в реакте. Я постоянно спотыкаюсь на то что у меня каких-то хуках prev с текущим стейты с пропами одинаковы и вот эта лажа тоже говорит о кривых сетстейтах.
    Компоненты у меня здоровые, я использую как правило колбэк для изменения стейта, забираю этот стейт в колбэке, как-то видоизменяю и возвращаю его заассайненую версию.
    Вот, к примеру метод сета состояния визарта после запроса с сервера:
    setWizardState(data) {
            // выставил доп ключи, которые не нужны на сервере
            Object.keys(data.steps).forEach(stepKey => {
                data.steps[stepKey]['forcedOpen'] = false;
            });
            console.log('old state: ', Object.assign({}, this.state))
            if (this.state.wizard.steps !== data.steps) {
                this.setState(state => {
                    state.wizard.steps = data.steps;
                    state.wizard.active = true;
                    return Object.assign({}, {wizard: state.wizard})
                }, () => {
                    console.log('new state: ', Object.assign({}, this.state))
                    if (this.state.wizard.steps.company.status === 'next') {
                        // если следующий таб в визарде next, я лочу ссылку на него
                        this.lockTab('company')
                    };
                    // запрос к настройкам текущего таба, которые попадут в его компонент пропсом
                    this.requestDataByRoute();
                })
            }
        }

    Интересно что несмотря на assign логи возвращают мне ссылки на текущий стейт.
    Но блин, как тогда скопировать объект возвращаемый из setState полностью? Там же туча вложенностей.
    Ну или вот к примеру, закрытие и открытие окна визарда - я возвращаю только wizard в сетстейте. Какого он мне обновил весь текущий компонент включая те что получают пропы из табов (которые пососедству с wizard)
    toggleWizard(value) {
            this.setState(state => {
                state.wizard.active = value;
                return {wizard: state.wizard}
            })
        }

    Писал на вью беды не знал, дёрнул меня чорт подписаться на проект на реакте......
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дольше писать компоненты. Много "лишнего" кода. Но и проще тоже становится


    Сергей Сунцев, вы сами себе противоречите. В большой команде и сложных проектах простота и читаемость кода превыше всего - а реакт крайне свободомысленный фрейм. Большие команды - я убедился на собственном опыте - всегда выбирают ангуляр. Ибо на каждый чих своя строго задекларированная салфетка, ещё и полная поддержка ts из коробки. А чем шаблоннее прогры больших проектов пишут код, тем легче искать им замену, подхватывать эстафету ну и так далее
  • Можно ли отрендерить реакт-компонент императивно?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Роман Александрович, Bingo!
    https://ru.reactjs.org/blog/2015/10/01/react-rende...
    И это работает. Для императивного вызова пришлось создать отдельный класс, который как я и думал не будет наследовать реакт. Его основное отличие в том, что рендер вызывается в конце конструктора. Объединить их уже не выйдет, но и не страшно. Всё равно у обоих обёрток разная цель применения
    class AlertCaller {
        constructor(options) {
            this.state = {
                children: options.textError
            }
            this._render();
        }
        
        _render() {
            console.log(this.state)
            ReactDOM.render(
            <Alert {...this.state} />,
            document.getElementById("alerts")
            );
        }
        destroy() {
            ReactDOM.unmountComponentAtNode(this._container);
        }
    }

    Ну и AlertRenderer остался для вызова алертов, завязаных на стейт приложения.
  • Можно ли отрендерить реакт-компонент императивно?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Роман Александрович, реакт вставил палку в колесо.
    Запорталить можно только в рендер-функции. Если я сохраняю new AlertRenderer в переменную, он не вызывает render-функцию, и forceUpdate я выполнить не могу.
    // тот самый
    class AlertRenderer extends React.Component {
        constructor(props) {
            super(props)
            this.state = {...props}
        }
        /*
        options
            errorText - string
        */
        setNewAlert(options) {
            this.setState(state => {
                state.children = options.errorText
                state.warning = true;
                return Object.assign({}, state)
            }, () => {
                this.forceUpdate()
            })
        }
        render() {
            return ReactDOM.createPortal(<Alert {...this.props}/>, document.getElementById("alerts"));
        }
    }

    Я попытался вручную его зарендерить, но реактДОМ жалуется
    const alert = new AlertRenderer();
    document.getElementById('alerts').innerHTML = alert.render();
    // получил Uncaught Invariant Violation: Target container is not a DOM element. от reactDOM
  • Можно ли отрендерить реакт-компонент императивно?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Роман Александрович, ну это какой-то лихой топорик, но можно копнуть и в его сторону. Попробую создать метод в рендерере алерта, через который прокину в алерт нужные пропы и вызову этот forceUpdate. Отпишусь как получится
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Сергей Сунцев, я против сторов как таковых и везде. Мне не нравится flux-подход. Я считаю что при грамотном распределении сквозной функциональности стор не нужен и он только всё усложняет
  • Как выводить спрайт svg в зависимости от data элемента на странице?

    ShadowOfCasper
    @ShadowOfCasper
    Genri_Rus, очень плохой подход городить всё в один файл. Если твой код будет в будущем допиливаться ребятами типа меня - тебя будут вспоминать массой нехороших слов)
    Ну а это пока ты так по неопытности говоришь, со временем и до вебпака дорастёшь, и jquery выкинешь
  • Как выводить спрайт svg в зависимости от data элемента на странице?

    ShadowOfCasper
    @ShadowOfCasper
    Genri_Rus, конечно, почему нет. Просто собирай вебпаком чтоб выглядело это всё поддерживаемо.
    Сам объект держи в отдельном файле, импортируй туда иконки через импорты. svg это такой же html как и span. И вставляя его в innerHTML он отренерится как и span и любой другой элемент
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дмитрий, да, это определённо решение и не такое упоротый код получается. Не сказать что универсально, но хотя бы реально все биндинги вынести в утилиты.
    Теперь я понимаю всю суть этого мемасика))))
    junior-react-developer-vs-senior-react-d
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дмитрий, немного пораскинув мозгами я прокинул контекст явно и это заработало.
    Теперь биндинг выглядит так:
    onChange={updateField.bind(this, 'login', this)
    А сама импортируемая функция так:
    const updateField = (fieldKey, context, event) => {
        const value = event.target.value;
        context.setState((state) => {
            state[fieldKey].value = value;
            return Object.assign({}, state)
        })
    }
  • Как выводить спрайт svg в зависимости от data элемента на странице?

    ShadowOfCasper
    @ShadowOfCasper
    Genri_Rus, дык да, допиши. Вообще я б вебпаком извлекал это всё и не в индексный массив, а в объект с ключами. ключ - иконка, ключ - иконка.
    Потом создал модуль, который перебирал бы все селекторы, к которые нужно вставить иконки:
    $('.icon').each((item) => {
      let currentIconCode = $(item).data('icon'),
      // где iconObject - мой плоский объект с иконками
      iconContent = IconObject[currentIconCode]
      $(item).html(iconContent)
    })
  • Как убрать ошибку в npm?

    ShadowOfCasper
    @ShadowOfCasper
    kolykisel, вообще вряд ли ну ты лучше выясни опытным путём
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дмитрий, как я и думал это не заработало. У меня в updateField с onChange прилетал event - я ж не просто так его забиндил:
    onChange={this.updateField.bind(this, 'email')}
    Ивент то прилетает, только fieldKey я теперь пробросить не могу.
    onChange={updateField(this, 'login')}
    Уже как таковое неверно. Реакт исполнит updateField вместо биндинга
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дмитрий, я попробую, но мне нужен функциональный сетстейт. Как видите по примеру, стейты компонентов имеют сложную структуру и если я отдам в setState объект вместо колбэка, я точно отгребу ошибок
  • Как убрать ошибку в npm?

    ShadowOfCasper
    @ShadowOfCasper
    kolykisel, ну тогда совсем печаль. убедись что npm стоит последний, потри package-lock с node_modules и npm i по новой. Если и это не поможет то тут где-то в ls модуле npm косяк закрался. И тогда тут только писать в npm на github новую issue и ждать от них ответа
  • Как выводить спрайт svg в зависимости от data элемента на странице?

    ShadowOfCasper
    @ShadowOfCasper
    Да какие бы они ни были сложные, это неважно. Приведи всех к одному вьюбоксу и выпили все fill и stroke из разметки, наследуй их через css.
    Про ховер - расставь на circle нужные селекторы и в css по hover залей как хочешь
  • Где двусторонний дата-биндинг?

    ShadowOfCasper
    @ShadowOfCasper Автор вопроса
    Дмитрий, естественно.
    Пример. Есть login, есть register, у обоих компонентов есть одна и та же функция биндинга. Она абсолютно идентична, но я не могу её вынести в хок потому что у него совсем другой стейт:
    //Рега
    class Register extends React.Component {
        constructor(props) {
            super(props)
            this.updateField = this.updateField.bind(this)
            this.state = {
                profileName: {
                    valid: true,
                    value: ''
                },
                email: {
                    valid: true,
                    value: ''
                },
                confPass: {
                    valid: true,
                    value: ''
                }
            }
        }
    // явный биндинг
        updateField(fieldKey, e) {
            const value = e.target.value;
            this.setState((state) => {
                state[fieldKey].value = value;
                return Object.assign({}, state)
            })
        }
        render() {
            return <div className='auth__reg'>
                <div className='auth__card'>
                    <Input className='auth__input'
                        labelInside
                        value={this.state.profileName.value}
                        label={
                            <Translation>
                                {t => t('auth.label.profile')}
                            </Translation>
                        }
                        onChange={this.updateField.bind(this, 'profileName')}/>
                    <Input className='auth__input'
                        labelInside
                        value={this.state.email.value}
                        label={
                            <Translation>
                                {t => t('auth.label.email')}
                            </Translation>
                        }
                        onChange={this.updateField.bind(this, 'email')}/>
                    <Input className='auth__input'
                        labelInside password
                        value={this.state.password.value}
                        label={
                            <Translation>
                                {t => t('auth.label.setPass')}
                            </Translation>
                        }
                        onChange={this.updateField.bind(this, 'password')}/>
                    <Input className='auth__input'
                        labelInside password
                        value={this.state.confPass.value}
                        label={
                            <Translation>
                                {t => t('auth.label.confirmPass')}
                            </Translation>
                        }
                        onChange={this.updateField.bind(this, 'confPass')}/>
                   
                </div>
            </div>
        }
    }
    
    //логин
    class Login extends React.Component {
        constructor(props) {
            super(props);
            this.updateField = this.updateField.bind(this)
            this.state = {
                remember: true,
                login: {
                    value: ''
                }
            }
        }
    // и вот она снова... 
        updateField(fieldKey, e) {
            const value = e.target.value;
            this.setState((state) => {
                state[fieldKey].value = value;
                return Object.assign({}, state)
            })
        }
    
        render() {
            return <div className='auth__login'>
                <div className='auth__card'>
                    <Input className='auth__input'
                        labelInside
                        value={this.state.login.value}
                        label={
                            <Translation>
                                {t => t('auth.label.login')}
                            </Translation>
                        }
                        onChange={this.updateField.bind(this, 'login')}/>
                </div>
            </div>
        }
    }

    Лишние куски я выпилил
  • Как убрать ошибку в npm?

    ShadowOfCasper
    @ShadowOfCasper
    kolykisel, без сарказма, ярлык должен помочь. Но зреть же надо в корень проблемы, верно?) С вендой вечные проблемы путей. Эта система бесит всех nodejs разрабов потому что требует повсеместное использование path.resolve(). И меня она тоже бесит, вернее бесила в далёком прошлом когда я попытался работать с нодой под вендой. Это далеко не первая и не последняя npm ошибка, которую ты отхватишь именно под этой системой