Ответы пользователя по тегу React
  • Как использовать миксины в React.js ES6/7?

    Да, миксинов теперь нету. Используйте декоратры -> https://github.com/brigand/react-mixin
    Ответ написан
    Комментировать
  • React и Flux: как получить данные при загрузке страницы?

    Store.fetchData() возвращает Promise. Вам нужно дождаться пока придет ответ и потом уже рендерить Ваш компонент.

    Store.fetchData().then( ... )

    Или подписываться на Store каким-либо образом (зависит от выбранной реализации flux)
    Store.on('DATA_LOADED', (data) => this.setState({ data }); //как пример
    Ответ написан
    3 комментария
  • Нужно ли при POST запросе делать reducer в redux'е?

    Редьюсер нужен когда Вы хотите хранить состояние. Это может быть, например, статус запроса - упех/в процессе/ошибка. И исходя из этого сделать кнопку "отправить" не активной, показать индикатор загрузки и т.д.
    Ответ написан
    1 комментарий
  • Какой изоморфный роутер выбрать для ReactJS?

    По мне так react-router - лучшее решение. С гет запросами проблем ни каких, потому что он не обрабатывает гет запросы)

    Все библиотеки новые, эта ниша только развивается, так что решений "проверенных временем" сейчас нету.

    UPD1:
    copal: вот только что тыкал как псих - все работает. Если только загрузить страницу и сразу кликнуть - может возникнуть ситуация, что роутер еще не включился и тогда ссылка отработает как простая ссылка - с сервера загрузится новая страница.
    Ответ написан
    2 комментария
  • Как в React не показывать кусок компонента?

    Если условие небольшое, то можно не выносить в отдельную функцию (как предложил OneFive )

    renderAlert() {
      return (
        <Alert bsStyle="warning" onDismiss={this.hideAlertByClick}>
            <strong>Внимание</strong> - эксперементальный проект, в стадии разработки. Заявленные функции будут подключаться по мере его развития.
        </Alert>
      );
    }
    
    render() {
      const { showAlert } = this.state;
      return (
        <div>
            <b> Some text </b>
            { showAlert && this.renderAlert() }
        </div>
      );
    }
    Ответ написан
    Комментировать
  • Как правильно получать и обрабатывать данные из форм в React.js?

    Воспользуйтесь, например, этой библиотекой -> https://github.com/erikras/redux-form .В ней есть поддержка динамических форм. Все поля будут по факту в одном объекте и относительно этого Вы можете применять свою логику рендера\расчетов.
    Ответ написан
    Комментировать
  • Как выполнить экшен после выполнения другого екшена?

    Единственный способ нативно в редаксе выполнять экшены в определенном порядке - это thunk
    functiob action1Creator() {
      return (dispatch, getState) => {
        fetch(...)
          .then(JSON.parse)
          .then((response) => dispatch(action2Creator(response)))
        ;
      };
    }
    
    function action2Creator(response) {
      return { type: 'SOME', data: response.data[12] };
    }
    Ответ написан
    Комментировать
  • Объясните простыми словами как работает Redux?

    У вас есть одно большое дерево, в котором хранится все состояние (state) приложения - это хранилище (store).
    Также у вас есть набор редьюсеров (которые скомбинированы в один общий rootReducer) - это функции, который принимают текущее состояние и действие и возвращают новое состояние:
    function someReducer(state = initialState, action) {
      // обычно выглядит как switch 
      // action - простой js-объект
      //              и обязательно имеет строковое поле type
      switch(action.type) {
        // обрабатываем действие с типом SOME_ACTION_NAME
        case 'SOME_ACTION_NAME':
          // берем какие-то данные из экшена и возвращаем новое состояние
          // при этом менять sate нельзя!
          // state.someProperty = action.newStateData <--- НЕТ!
          return { ...state, action.newStateData };
        // Если мы не обрабатываем действие - просто возвращаем старое состояние
        default:
          return state;
      }
    }


    Также есть экшен креаторы (actionCreators) - это функции, которые возвращают действие. затем это действие вещается в хранилище (диспатчится). Типичный пример:
    function someActionCreator(someArg) {
      return {
        type: 'SOME_ACTION_NAME',
        newStateData: someArg + 5, // <-- разная логика
      };
    }


    По-умолчанию в качестве экшена мы можем вернуть только простой объект, но при создании хранилища можно добавить так называемый middleWare. Это специальные функции, которые принимают все экшены из диспатча и могут передавать их дальше (при этом содержат дополнительную логику).

    Если мы хотим получить доступ к состоянию в экшен креаторе - воспользуемся thunkMiddleware:
    import thunkMiddleware from 'redux-thunk';
    
    function createStore(initialState) {
      const reducer = combineReducers(reducers);
      const finalCreateStore = applyMiddleware(
        thunkMiddleware // <-- добавляем middleware
      )(defaultCreateStore);
      return finalCreateStore(reducer, initialState);
    }


    Теперь мы можем делать так:
    function someActionCreator(someArg) {
      return (dispatch, getState) => { // <-- возвращаем фукнцию, а не объект!
        const someState = getState().reducerName;
        return {
          type: 'SOME_ACTION_NAME',
          newStateData: someArg + someState, 
        };
      };
    }


    В общем схема выглядит так:

    actionCreator --action--> dispatch --action--> middleware --action--> store --action--> reducer --> newState


    Затем мы берем из react-redux метод connect, который подключает Ваш умный компонент к хранилищу:
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    
    class MyComponent extends Component {
      static propTypes = {
        someProp: PropTypes.string.isRequired,
        someFunc: PropTypes.func.isRequired,
      };
    }
    
    // Тут мы берем из глобального состояния необходимую нам часть
    // В ownProps - свойства компонента. Тут могут быть например свойства от роутера
    function mapStateToProps(state, ownProps) {
      return {
        someProp: state.someReducer,
      };
    }
    
    function mapActionsToProps(dispatch) {
      return bindActionCreators ({ // <-- биндим все на disptach для удобства
        someFunc: (someArg) => someActionCreator(someArg + 1),
      }, dispatch);
    }
    
    export default connect(
      mapStateToProps,
      mapActionsToProps
    )(MyComponent);
    Ответ написан
    3 комментария
  • Где и как нужно сделать AJAX запрос в redux?

    Для работы с promise Вам нужно использовать дополнительный middleware - promise middleware. Существует несколько реализаций - можете выбрать любой понравившийся. Я использую этот и относительно него буду далее писать.

    Как я понял, запрос пишется в action creator при помощи промиса


    Да, все так. В экшен-креаторе делаем запрос, возвращаем экшен с промисом. Далее promiseMiddleware подхватывает его и вместо одного экшена диспатчит 3 - действие началось, действие завершилось успешно, действие завершилось с ошибкой. Все это происходит в зависимости от того в какое состояние попал вышеупомянутый promise. Другими словами - "действие началось" диспатчится сразу; если запрос успешен - диспатчится "действие завершилось успешно".
    Соответственно в вашем редьюсере Вы подписываетесь на это три действия. Пример:

    // action creator
    import fetch from 'isomorphic-fetch';
    
    export default function getBook() {
      // Для запросов чаще всего используется  isomorphic-fetch, который возвращает promise
      const promise = fetch(url, options);
      return {
        types:  [ 'GET_BOOK-BEGIN', 'GET_BOOK-SUCCESS', 'GET_BOOK-FAILURE' ],
        promise,
      };
    }


    // reducer
    import {GET_BOOK} from '../actions/books';
    
    const booksReducer = (state = {}, action) => {
      switch (action.type) {
        case 'GET_BOOK-SUCCESS':
          // При успешном завершении у нас установлено свойство result с ответом сервера
          return action.result;
        case 'GET_BOOK-FAILURE':
          // При неудачном завершении у нас установлено свойство error с описанием ошибки
          doSomethingWithError(action.error); // <--- просто для примера
        default:
          return state;
      }
    };
    
    export default booksReducer;


    UPD1 К слову: у редакса есть отличный пример, где все это можно в живую посмотреть - https://github.com/rackt/redux/tree/master/example...
    Ответ написан
    6 комментариев
  • Как на React сделать вертикальное меню с выделением элемента меню?

    Надо, чтобы при нажатии на элемент меню он выделялся другим цветом. Это все получилось сделать.

    Странно, что одно работает, а другое - нет. Механизм ведь один и тот-же. Простейшая реализация предполагает сохранение выбранного элемента меню в state:

    class MyMenu extends React.Component {
    
      constructor(props) {
        super(props);
        this.handleItemClick = this.handleItemClick.bind(this);
        this.state = { selectedItem: null };
      }
    
      handleItemClick(selectedItem) {
        console.log('handleItemClick', selectedItem);
        this.setState({ selectedItem });
      }
    
      render() {
        const { items } = this.props;
        const { selectedItem } = this.state;
        const { handleItemClick } = this;
    
        return (
          <ul>
            { items.map( (item, key) => (
                <MenuItem
                    key={key}
                    item={item}
                    isActive={item === selectedItem}
                    onClick={handleItemClick}
                 />
            )) }
          </ul>
        );
      }
    }


    И, соответственно, в самом компоненте MenuItem проверяем - если флаг isActive === true, то добавляем класс или еще чего:
    Рабочий пример
    Ответ написан
    1 комментарий
  • Как исправить ошибку "Invariant Violation: Objects are not valid as a React child"?

    Что вы пытаетесь сделать в методе рендер? Ошибка говорит о том, что вы вместо реакт-элемента рендерите объект(ы).

    Вам нужно сначала отфильтровать книги, а потом отрендерить их как элементы списка:

    render() {
        const {books, url} = this.props;
        return (
          <ul>
            {books.filter(book => book.name === url).map((book, key) => (
              <li key={key}>
                  <p>{book.name}</p>
                  <p><Link to={`/${book.author}`}>{book.author}</Link></p>
                  <p>{book.descrip}</p>
                </li>
            ))}
          </ul>
        );
      }
    Ответ написан
    2 комментария
  • Почему в React.js в событии onKeyUp не работает event.preventDefault()?

    а как же тогда сделать, так, чтоб если пользователь вводит в строку значение, которое не соответсвует регулярному выражению - выполнялась функция event.preventDefault() ? ведь keyDown и keyPress для этого не подходят, так как они берут старые занчения


    У вас подход в корне неправильный. Ваш инпут находится в состоянии uncontrolled. И вам нужно вместо этого сделать так:
    <input type="text" value={someValue} onChange={handleChangeSomeValue}/>

    handleChangeSomeValue(e) {
        const nextVal = e.currentTarget.value;
        if (!isValid(nextVal)) {
          return;
        }
        this.setState({ someValue: nextVal });
      }


    Рабочий пример -> jsfiddle.net/yuvuyrhv/20
    Ну и читаем документацию -> https://facebook.github.io/react/docs/forms.html
    Ответ написан
    Комментировать
  • Как создать простое приложение на react-native?

    У вас слишком общий вопрос.
    Посмотрите https://rnplay.org/ . Документацию. Вы знакомы с реактом? Если нет - то сначала освойтесь с ним.

    Переходы по страницам осуществляются так же, как и на react'e для web - react router, например
    Ответ написан
    5 комментариев
  • Как правильно работать/подключать sass/css в React.js?

    Попробуйте style-loader:
    import styles from 'styles.less';
    ...
    componentDidMount() {
      styles.use();
    }
    
    componentWillUnmount() {
      styles.unuse();
    }


    Тогда стили будут добавляться на страницу, когда компонент будет установлен. Но мне как-то не особо такой подход нравится и я просто делаю файл styles.less куда импортирую все нужные мне стили компонентов. И у меня на роут 'GET /styles.css' стоит обработчик, который отдает скомпиленный styles.less

    Аналогичное решение будет и для sass\postCss ...
    Ответ написан
  • Есть ли способ не привязывать каждую функцию в которой нужен this в ES6 React?

    В babel с пометкой stage-0 есть такая штука - https://github.com/jeffmo/es-class-static-properti...

    Она позволяет делать так:

    class MyClass {
      foo = () => {
        console.log('foo a = ', this.a);
      }
    
      bar = () => {
        this.a = 10;
        setTimeout(this.foo, 10); // Мы не биндим foo на this
      }
    }
    
    const o = new MyClass();
    const bar = o.bar; // и тут тоже не биндим
    
    bar(); // выводит "foo a = 10"
    Ответ написан
    Комментировать
  • Как добавить данные в массив через foreach в react?

    1. push мутирует массив. Читаем это и никогда не мутируем state. На ES6 добавить элемент в массив можно так:

    this.setState({ massiv: [ ...this.state.massiv, "новый элемент"  ] })


    2. Данные компоненты должны получать только через props. Конечно, некоторые из компонентов у вас будут как controller-view (подключены к store и будут получать данные через события\конекст\еще как-нибудь), но таких контроллеров должно быть мало, реально мало - в основном на верхних уровнях дерева.

    3. По поводу ajaxa - выносите такую логику в бизнес-слой. В ваши action creators, например. Тогда у вас не возникнет таких проблем: делаете запрос -> когда он завершится отправляете соответствующий action (success, failure) -> store обрабатывает экшен, изменяет свое состояние -> controller view получает новые данные и рендерится

    4. В ES6 есть промисы
    const someArr = [];
    const doAjaxJob = el => fetch('some-url', .... );
    const p = Promise.all(someArr.map(doAjaxJob)); // <-- сюда можно подписаться


    PS И главное - не превращайте хороший функциональный стиль в спагетти
    Ответ написан
    Комментировать
  • Как добавить элемент в форму по клику в React?

    Я набросал пример - jsfiddle.net/yuvuyrhv/19

    class MyForm extends React.Component {
    
      constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.addGood = this.addGood.bind(this);
        this.changeGoodCount = this.changeGoodCount.bind(this);
        this.state = { goods: [] };
      }
    
      handleSubmit() {
        console.log('handleSubmit');
      }
    
      addGood() {
        const { goods } = this.state;
        this.setState({ goods: [ ...goods, { count: 0 } ] });
      }
    
      changeGoodCount(n, count) {
        const { goods } = this.state;
        this.setState({ goods: goods.map( (good, i) => i === n ? { count } : good ) });
      }
    
      render() {
        const { goods } = this.state;
        const { handleSubmit, addGood, changeGoodCount } = this;
        console.log('MyForm.render() -> goods =', goods);
        return (
          <form onSubmit={handleSubmit}>
          	<div>
              Имя пользователя: <input type="text" />
            </div>
            <div>
              Телефон: <input type="text" />
            </div>
            <div>
              { goods.map( (good, i) => <GoodInput key={i} good={good} n={i} onChange={changeGoodCount}/> ) }
            </div>
            <div>
              <button type="button" onClick={addGood}>Добавить что-либо</button>
            </div>
          </form>
        );
      }
    }
    
    class GoodInput extends React.Component {
      handleChange(e) {
        const { n, onChange } = this.props;
        const count = e.currentTarget.value;
        onChange(n, count);
      }
    
      render() {
        const { good, n } = this.props;
        return ( 
          <div>
            Количество товара {n} <input type="text" onChange={(e) => this.handleChange(e)} />
          </div>
        );
      }
    }


    Идея, надеюсь, ясна. В итоге подключите к вашим сторам все это, уберете стейт, добавить проп тайпс, добавите обработчики onChange на все инпуты и так далее...
    Ответ написан
    2 комментария