Ответы пользователя по тегу React
  • Как в react-router сделать сайдбар опциональным?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Можно сделать 2 разных "разметки", так сказать. В одной у вас есть сайдбар, в другой нет.
    2 разные разметки = 2 разных компонента (роут-с-сайдбаром, роут-без-сайдбара).
    Оборачиваете дочерние роуты в роут-с-сайдбаром, или в роут-без-сайдбара и там рисуете нужный шаблон + this.props.children. Вложенность роутов друг в друга - любая, можно таким образом еще усложнить логику отрисовки шаблона.

    p.s. 4ю версию роута еще не смотрел. Но таким решением пользуюсь с 3й версией, думаю в 4м так же, либо еще удобнее придумали.

    p.p.s. тема с фильтрацией, которую посоветовал Aves тоже подходит.

    (пример, используется getComponent - это для динамической подгрузки)
    <Route path='/reports' component={AuthenticatedContainer} onEnter={_ensureAuthenticated}>
      <Route getComponent={() => def(import('../containers/WiwthSidebar'))}>
        <Route path='/reports/a' getComponent={() => def(import('../containers/A'))} />
        <Route path='/reports/b' getComponent={() => def(import('../containers/B'))} />
      </Route>
      <Route getComponent={() => def(import('../containers/WithoutSideber'))}>
        <Route path='/reports/c' getComponent={() => def(import('../containers/C'))} />
      </Route>
    </Route>
    Ответ написан
    Комментировать
  • Что делать с огромным файлом скриптов React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Это уже файл после "разбивания на кусочки" (для гугления - code splitting) ?
    Грузите то, что нужно определенному роуту и будет получше.

    гугление не даст полной картинки сразу, но постепенно соберется.

    Потребуется использовать getComponent из React-router, а далее webpack 2 уже сам сделает почти все...

    Выглядит так:
    function def(promise) {
      return promise.then(cmp => {
        console.info('Dynamic loaded by route: ', cmp.default.displayName) // для тестирования можете логировать имя компонента
        return cmp.default
      })
    }
    
    ...
    <Route path='/signin' getComponent={() => def(import('../containers/SigninContainer'))} />
    ...
    Ответ написан
    3 комментария
  • Что нужно знать перед изучением angular и react?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    1) по нововведениям почитайте у Кантора
    2) далее сделайте пример из оф.доки
    3) далее по аналогии с примером из оф.доки, чуть-чуть измените что-нибудь и сделайте по-своему
    4) если речь про react, то с усложнением примера, начнется медленный переход в сторону "нужен redux/подобные ему" -> читайте доку, продолжайте накручивать пример.

    p.s. если пример вам интересен, то прогресс будет быстрее, поэтому стоит поработать с API интересных вам сайтов, steam, vk, ...
    Ответ написан
    Комментировать
  • Как сделать страницу 404, в проекте, где внутри Route есть другие Route?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Добавьте его 1 раз в самом низу.

    ReactDOM.render(
      <Router history={browserHistory}>
        <Route path="/" component={Layout}>
          <Route path="/sing" component={SignUp}/>
          <Route path="/profile" component={Profile} />
          <Route path="/register_approve" component={Validation} />
          <Route path="/forgot_password" component={ForgotPassword} />
          <Route path="/confirm_email" component={ConfirmEmail} />
          <Route path="/restore_password/:token" component={RestorePassword} />
          <Route path="/confirm_invite" component={ConfirmInvite} />
          <Route path="/my-cabinet" component={Cabinet} />
          <Route path="/members" component={Members} />
          <Route path="/invite-member" component={InviteMember} />
    
          <Route path="/not_access" component={NotAccess} />
    
          <Route path="/finance" component={Finance}>
            <Route path="/finance/project" component={FinanceProject}/>
            <Route path="/finance/fixed-costs" component={FinanceFixedCost}/>
            <Route path="/finance/fixed-costs" component={FinanceFixedCost}/>
            <Route path="/finance/salary" component={FinanceSalary}/>
            <Route path="/finance/other" component={FinanceOther}/>
          </Route>
        </Route>
        <Route path="*" component={NotFound} />
      </Router>,
      document.getElementById('root')
    Ответ написан
    2 комментария
  • Как вывести данные с сервера без lodash?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Vlad Feninets ответил абсолютно верно, приведу полную реализацию, на основе кода из репозитория:

    return Object.keys(this.props.posts).map(postId => {
          const currentPost = this.props.posts[postId]
          return (
            <li className="list-group-item" key={currentPost.id}>
              <span className="pull-xs-right">{currentPost.categories}</span>
              <strong>{currentPost.title}</strong>
            </li>
          );
        })
    Ответ написан
    Комментировать
  • Какой подход (библиотеки, фреймворки) используете при верстке UI?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Всякие красивые чекбоксы, радиобаттоны и прочие интерфейсы верстаю вручную, и естесственно адаптивно.

    Значит при том вы ведете какую-то свою "библиотеку подобных элементов"?
    Так же и другие люди, "ведут" подобные библиотеки, еще больше других людей их используют и пишут о багах, поэтому получается обычно более "протестированный" элемент.

    Пример, для material design - https://getmdl.io/components/index.html
    Там есть github и можно посмотреть код любого компонента... а можно просто взять сразу готовый и использовать, при этом не писать самому.

    Другой пример: есть популярный bootstrap, есть у него сетка, по этой сетке делается много однотипных сайтов, дизайнеры по ней рисуют сразу изначально, в итоге у рядового "конвейрного" мастера по лендингам (ничего плохого не имею против таких специалистов) очень сильно понижается затраченное время на выполнение задачи по адаптивной верстке.
    ===

    По технологиям: вы верстаете, так наверное, используете gulp? Если нет - то пора, получите live reload (не нужно перезагружать страницу), сможете оптимизировать ваши скрипты/стили/картинки... и все это будет сильно высвобождать ваше время.
    Ответ написан
    3 комментария
  • Как реализовать грамотную проверку авторизации?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Вы используете react-router? Если да, то тут все просто:
    1) роуты создаются с помощью функции, таким образом вы можете прокинуть в роутинг store
    ...
    import configRoutes from '../../routes'
    ...
    render() {
      return (
        <Provider store={store}>
          <Router history={routerHistory}>
            {configRoutes(store)}
          </Router>
        </Provider>
      )
    }


    2) Далее в роутинге, устанавливаете на "защищенные" компоненты onEnter hook:
    ...
    <Route path='/secret-area' component={SecretAreaContainer} onEnter={_ensureAuthenticated}>
    ...


    3) сама функция, смотрит есть ли в store необходимые данные:
    export default function configRoutes(store) {
      function _ensureAuthenticated(nextState, replace, callback) {
        const { dispatch } = store
        const { session } = store.getState()
        const { currentUser } = session // данные по юзеру
        let nextUrl
    
        if (!currentUser && localStorage.getItem('token')) {
            dispatch(getCurrentAccount())
          }
        } else if (!localStorage.getItem('token')) {
          nextUrl = location.pathname + location.search.replace('?', '&')
          replace('/signin')
        }
    
        callback()
      }
    
      // здесь ваши роуты


    Ок, по роутам готово.

    Теперь, по переадресации:
    - на success в логине, делаете редирект куда угодно:
    export function signIn(email, password) {
      return (dispatch, getState) => {
    
        dispatch({
          type: USER_SIGN_IN_REQUEST,
        })
    
        const params = {
          email,
          password,
        }
    
        httpPost(`${API_ROOT_V1}/api/authenticate`, params)
          .then((data) => {
            saveParamsToLS(data) // здесь токен можно сохранить, например
            dispatch(push('/account')) // ваш РЕДИРЕКТ, используется push из react-router-redux (что необязательно)
          })
          .catch((error) => {
            console.warn(`Sign in error: ${JSON.stringify(error)}`) //eslint-disable-line no-console
            dispatch({
              type: USER_SIGN_IN_FAILURE,
              error: error,
            })
          })
      }
    }


    и остается кейс с прямым заходом: вы должны разрулить это опять же в onEnter хуке в роутере. Так как у вас есть store, и вам доступны все данные из него, включая store.dispatch метод, добить пример не составит труда.
    Ответ написан
    3 комментария
  • Как настроить деплой с разных веток для SPA приложения?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Вам нужно использовать github webhooks.
    p.s. гугл
    Ответ написан
    Комментировать
  • Как работает использование Redux вместе со state?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В вашем примере, нет главного - как вы отрисовываете минуты/часы? Через state или через props? Redux не важно используете вы state или нет, реакт-компоненту - не важно используете вы redux или нет.

    Обновлять state на основе пришедших с помощью Redux props вы можете в componentWillReceiveProps
    Ответ написан
    5 комментариев
  • React router: как применять разные файлы стилей к разным страницам?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Но там, где он не нужен, все равно применялся.

    Применяется он, потому что вы вынесли стили в отдельные компоненты, но они при этом грузятся у вас, наверняка, в тэг style, либо в один единственный файл и это подключается все "наверху", следовательно, хоть и стили там где необходимо подключены - они есть для всего сайта, значит будут применяться.

    Чтобы отказаться на некоторых страницах, нужно не использовать одинаковые с bootstrap имена классов на этих страницах. "Поинтереснее" решения подсказать не могу.
    Ответ написан
    Комментировать
  • В каких случаях использовать PureComponent?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Годная статья с хабра (плюс комментарии)
    Ответ написан
    1 комментарий
  • Redux thunk, откуда береться dispatch в экшине?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Он берется из middleware redux-thunk

    Посмотрим на исходный код:

    function createThunkMiddleware(extraArgument) {
      return ({ dispatch, getState }) => next => action => {
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }
    
        return next(action);
      };
    }


    В котором видно, что если возвращаемый тип действия - function, то вызови все тоже самое, но с аргументами (dispatch, getState и extraArgument) - которые доступны через область видимости и являются тем "что надо".

    ca799e34804e4ae7afeaffa56751700d.jpg
    Ответ написан
    4 комментария
  • Почему первый респонс null?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Алексей Самсонов дело говорит. Нужно идти по массиву данных, когда он есть, либо когда вместо него "начальное состояние" = пустой массив.
    Судя по вашему вопросу, вам проще делать проверку, что если this.props.data.length есть, то рисуй шаблон, если нет - null

    renderTemplate(data) {
      return data.map(item => .... )
    }
    render() {
     ...
    { this.props.data.length ? this.renderTemplate(this.props.data) : null }
     ...
    }
    Ответ написан
    3 комментария
  • Нужна лучшая практика что бы убрать писанину в action?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Сначала тоже казалось "писанина", смотрел в сторону разных middleware'ов и т.д.
    А потом понял - что тут проблемы лично для меня никакой нет. Открываешь старый проект, на котором нашли баг/нужно что-то добавить - и вот оно, все просто по полочкам: есть действие пользователя -> есть action creator -> есть action с определенным типом -> есть reducer ... Достаточно 10 минут, чтобы освежить в памяти "что откуда и куда", поэтому я решил не придумывать и не усложнять.
    Ответ написан
    Комментировать
  • Почему родительский метод вызывается сам по себе?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В onClick нужно передавать функцию-обработчик, а вы передаете функция-обработчик() === результат вашей функции...
    То есть как только кнопка оказывается на странице, сразу же происходит вызов (круглые скобки).

    Пример:
    function myFunc(data) { console.log(data) }
    console.log( myFunc('test') ) => выведеть в консоль 'test'
    console.log( myFunc ) => выведеть в консоль function myFunc ...


    P.S. естественно, сразу возникает вопрос - как передать функцию + аргумент... Вам нужен либо метод bind, либо анонимная функция... Есть у разных подходов плюсы-минусы, но я тем не менее люблю использовать data-аттрибуты для этого.. тогда при передаче функции обработчик, у меня в event.target.dataset - есть все что нужно.

    P.P.S. когда возникают такие вопросы, значит нужно идти и копать основы, так как в дальнейшем только сильнее будет усиливаться непонимание между функциями, аргументами, полями свойств в props'ax и так далее... Начать по теории, рекомендую отсюда: https://learn.javascript.ru/function-basics, затем: https://learn.javascript.ru/introduction-browser-events
    Ответ написан
    1 комментарий
  • Как правильно выполнять ajax-запросы в react-router?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Запрос должен находиться либо в componentDidMount, либо в componentWillMount.
    Зачем вам componentDidUpdate?

    P.S. недавно меня спрашивали тоже самое, и если у вас проблема в том, что не "происходит" componentDidMount при изменении параметра роута, то здесь нужно использовать componentWIllReceiveProps(!)

    Пример: <Route path='/articles/:id' >
    Вы открываете браузер по URL адресу: /articles/1
    У вас в componentDidMount происходит вызов (например: getArticles(this.props.params.id)

    Затем вы кликая по ссылке, изменяете URL на /articles/2 и ожидаете что произойдет componentDidMount ? Нет, не произойдет, так как роут ('/articles/:id') не изменился, следовательно не было "демонтирования" и "примонтирования" компонента. Зато случилось "изменение props" в компоненте (того самого this.props.params.id), следовательно это можно обработать в componentWillReceiveProps
    Ответ написан
    3 комментария
  • ComponentWillMount vs ComponentDidMount, где лучше делать XHR к API?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Делайте в didMount, а по поводу:
    если в DidMount то контент может на некоторое время показаться без данных из сервера, или я не прав

    Вы правы, но для этого в шаблоне сделайте: если данных нет - пусто, если данные есть - рендери.. В таком случае для юзера это все будет выглядеть как загрузка страницы...
    Еще лучше, сразу крутить preloader например, и тд.
    Ответ написан
    Комментировать
  • Почему в React созданные функции(методы) вызываются без аргументов?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    // для примера обе переменные (store и dispatch) объявлены в той же области видимости
    // на самом деле их нет в вашем файле компонента
    // Так как функция connect вызывается "где-то там, где они доступны"
    // вы имеете к ним доступ
    let dispatch = () => console.log("dispatch")
    let store = { user: { name: 'Mike', age: 15 }, data: [1,2,3] }
    
    function connect(mapStateToProps, mapDispatchToProps) {
      console.log(mapStateToProps(store))
    }
    
    function mapStateToProps(storeFromClosure) { // здесь оказывается глобальный store доступный из замыкания
      return {
        myData: storeFromClosure.data 
      }
    }
    
    connect(mapStateToProps, null)
    Ответ написан
  • Как кастомизировать сторонний компонент React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Сторонний компонент, это обычно всего лишь "вьюха". Хорошие компоненты, таковыми и являются (пример) (react virtualized)

    Чтобы передать в него свойства - мы просто передаем свойства. Опять же, в качестве примера (react select 2). Передаем в него, например, options.
    Так же, у этого "хорошего" компонента, на изменение автором задуман onChange..
    <Select
    	name="form-field-name"
    	value="one"
    	options={options}
    	onChange={this.setUser} // тот самый onChange
    />

    Уже в нем можно смело "дергать" экшен-крейтор родителя, банально:
    // текущий компонент
    setUser(e) { this.props.setUser(e.target.value) }
    // родитель
    setUser(id) { this.props.actions.setUser(id) } // вызов redux action-creator


    В любом случае, вариантов обратится из потомка к родителю всего два. Причем первый используется в 90% случаев - это передать в props функцию-обработчик.
    Второй вариант, созданием компонентов-оберток используется реже и обычно уже на каких-то замороченных ситуациях.
    Ответ написан
    Комментировать
  • "Warning: Each child in an array or iterator should have a unique "key" prop." Как исправить?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Ошибка в том, что вы не передаете key, но пытаетесь его установить в
    renderDistrict(item, key)
    У вас функция принимает 2 аргумента, а вы передаете только один здесь:
    this.renderDistrict(item)

    Тем не менее, так как у вас есть id ваша задача решается так:
    renderDistrict(item) {
         return (
            <tr key ={item.id} className="districts">
                <td>{item.id}</td>
                <td>{item.name}</td>
            </tr>
         )
    }


    p.s. для продуктивного изучения react советую подтянуть знания javascript'a
    Ответ написан
    2 комментария