Ответы пользователя по тегу React
  • Функция connect() Redux, как правильно использовать?

    @SuperOleg39ru
    Front-end разработчик
    Множество connect компонентов, которые передают из store минимально необходимое количество данных - это верный подход, в таком случае компонент, обернутый в connect, будет обновляться только тогда, когда изменились реальные данные, от которых он зависит.

    По вашей проблеме:

    Представим, что в store у вас есть 2 свойства:
    1) options - массив строк для селекта
    2) selectedOption - выбранная строка (пустая по дефолту)

    И например одно действие - selectOption(option), для обновления selectedOption в store.

    Далее условные обернутые компоненты:
    // Ваш сайдбар обновится при каждом изменении selectedOption
    connect((state, ownProps) => ({ selectedOption: state.selectedOption }))(SidebarComponent)
    
    // Ваш селект обновляется в зависимости от изменения обоих свойств,
    // и используя свойство onSelect может обновить selectedOption самостоятельно
    connect(
      (state, ownProps) => ({ options: state.options, selectedOption: state.selectedOption }),
      (dispatch, ownProps) => ({ onSelect: (value) => dispatch(selectOption(value)) })
    )(SelectComponent)
    Ответ написан
  • Можно ли писать на React + JSX без Webpack? В чем минусы?

    @SuperOleg39ru
    Front-end разработчик
    https://codepen.io/anon/pen/EwLLbN

    Минусы - браузеру придется компилировать код на лету, это большая потеря в производительности.

    Писать на JSX позволяет babel, а не webpack, поэтому в примере на codepen добавлен скрипт с babel.
    Ответ написан
    Комментировать
  • Как вернуть контекст в данном случае?

    @SuperOleg39ru
    Front-end разработчик
    1 вариант - использовать стрелочные функции:

    method(function() {
    ...
    });
    
    // заменить на 
    method(() => {
    ...
    })


    2 вариант - привязать контекст к переменной:

    const that = this;
    that.context;


    Почитайте это
    Ответ написан
    2 комментария
  • Как протестить то, что случится после нажатия кнопки в React(Jest, enzyme)?

    @SuperOleg39ru
    Front-end разработчик
    На самом деле вам не нужно это тестировать.

    Разделяйте тестирование частей React + Redux приложения:

    1) Отдельно reducer и соответствующие actions, что делать очень просто, так как это чистые функции и простые объекты.

    2) Отдельно react компонент, и вы должны проверить только то, что при simulate('click') вызовется соответствующий обработчик.
    Пример:
    const props = {
        onClick: jest.fn()
    };
    let component;
    
    beforeEach(() => {
        component = enzyme.shallow(<Button {...props} />);
    });
    
    it('срабатывает событие onClick', () => {
        field.simulate('click');
        expect(props.onClick).toHaveBeenCalled();
    });


    Если вам нужно проверить, отреагировал ли компонент на изменение его свойств, то вы меняете его свойства напрямую через component.setProps({ key: 'value' });
    Ответ написан
    Комментировать
  • React.js. Доставка данных с сервера при первой загрузке и обновлении роута. Есть ли какие-то паттерны?

    @SuperOleg39ru
    Front-end разработчик
    У меня аналогичная ситуация, настраиваю react-router для нового приложения. Сразу скажу, что паттернов, кроме документации, не попадалось)

    В initialState для store вы сами решаете, что надо туда добавлять, в любом случае каждый редьюсер дает свой дефолтный кусочек общего state.

    По переходам - разделите данные на общие, которые нужны до старта приложения, и конкретные для компонентов.

    Про блок перехода - пример из документации, в зависимости от данных сверху, роут либо рендерит компонент, либо делает редирект.
    const PrivateRoute = ({ component: Component, ...rest }) => (
      <Route {...rest} render={props => (
        fakeAuth.isAuthenticated ? (
          <Component {...props}/>
        ) : (
          <Redirect to={{
            pathname: '/login',
            state: { from: props.location }
          }}/>
        )
      )}/>
    )


    Пример компонента, который запрашивает данные. Все свойства через connect, но вы можете так же менять и отслеживать состояние запроса в state.
    // getUsers - свойство из mapDispatchToProps, запрос на сервер, по завершению обновляет users в вашем Store
    // users - свойство из mapStateToProps
    class UserListContainer extends Component {
      componentWillMount() {
        this.props.getUsers();
      }
    
      render() {
        const { users } = this.props;
    
        if (!users) {
          return <Spinner />
        }
    
        return <UserList data={users} />
      }
    }


    В моем приложении я включаю spinner при старте приложения, и выключаю в компоненте, который рендерится после получения нужных данных. Например можно делать так (свойства и методы так же через connect).
    У вас будет крутиться прелоадер, пойдет запрос на токен, по успеху пойдет запрос на users, по успеху начнет рендериться UserListContainer, который должен выключить прелоадер.
    class App extends Component {
      render() {
        const { appIsReady } = this.props;
    
        // наш лоадер на весь экран при appIsReady: false
        return (
            <div>
              {!appIsReady && <Spinner style='fullscreen' />}
              </Switch>
                <Route path='/' exact={true} component={Home} />
                <Route component={NotFound} />
              <Switch>
            </div>
        );
      }
    }

    class Home extends Component {
      componentWillMount() {
        if (!this.props.token) {
          this.props.getToken();
        }
      }
    
      render() {
        const { token } = this.props;
    
        if (!token) {
          return null;
        }
    
        // UserListContainer в willMount меняет appIsReady на true
        return <Route path='/users' component={UserListContainer} />  
      }
    }
    Ответ написан
    Комментировать
  • React и асинхронные запросы?

    @SuperOleg39ru
    Front-end разработчик
    Для работы с API удобно будет взять готовую библиотеку, у которой методы http запросов возвращают промисы или объекты с аналогичными свойствами.
    Я могу посоветовать axios, в простом случае хватит и нативного метода fetch.

    Затем, вы можете создать отдельные классы - сервисы для работы с конкретными разделами API (например UsersService для работы со списком пользователей, AuthService для авторизации). И методы сервиса принимают необходимые аргументы, и возвращают методы axios (например UsersService.get(id) возвращает axios(`api/url/users/${id}`))

    И эти сервисы вы используете в ваших "умных" компонентах, в методе componentDidMount.

    Ссылка на статью с примером тут
    Ответ написан
    Комментировать
  • Для чего нужен react-router-redux?

    @SuperOleg39ru
    Front-end разработчик
    It is useful if you care about recording, persisti...

    Коротко - если используете Redux dev tools, хотите отслеживать там перемещения по роутам - используйте react-router-redux.
    Ответ написан
    4 комментария
  • Как настроить webpack-dev-server с использованием historyApiFallback?

    @SuperOleg39ru
    Front-end разработчик
    Webpack начинает искать файлы по неправильному пути, добавляет в начале /movie/ в вашем скрине.
    Не могу точно сказать в чем проблема, давайте попробуем так:

    Для начала замените output.filename: './dist/main.js' на:
    output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        }


    А publicPath: '/dist/' на:
    contentBase: path.resolve(__dirname, 'dist')

    И css выделяйте так - new ExtractTextPlugin('[name].css'), output.path уже указывает, что надо выгружать все в dist
    Ответ написан
  • Как обновить дочерний компонент из родительского?

    @SuperOleg39ru
    Front-end разработчик
    Во первых, вы объявили переменную btn, но не возвращаете ее в render.

    Во вторых, зачем объявлять в Child this.state свойство someVar, если оно доступно вам из this.props?

    Нет необходимости биндить this Child на коллбэк App, потому что тогда props.setVar метод будет вызывать setState у Child - this.props.setVar.bind(this, this.state.someVar)}

    Вкратце, React сам обновляет компонент, если изменились его props (что происходит через коллбэк родителя).

    export default class App extends Component {
        constructor(props) {
            super(props);
    
            this.state = {
                someVar: 0
            }
    
            this.setVar = this.setVar.bind(this);
        }
    
        setVar(some) {
            this.setState({someVar: some});
        }
    
       render() {
            return (<Child someVar={this.state.someVar} setVar={this.setVar} />);
       }
    }
    
    export default class Child extends Component {
        constructor(props) {
            super(props);
    
            this.handleClick = this.handleClick.bind(this);
            this.getNext = this.getNext.bind(this);
        }
    
        getNext() {
            return this.props.someVar + 1;
        }
    
        handleClick() {
            this.props.setVar( this.getNext() )
        }
    
       render() {
           let btn = (<button type="button" onClick={this.handleClick}>Go</button>
           return (<div><btn /> {this.props.someVar}</div>);
       }
    }
    Ответ написан
  • Правильный ли способ обновления данных в reducer?

    @SuperOleg39ru
    Front-end разработчик
    Сделайте декомпозицию редьюсера на несколько поменьше.
    ссылка
    Ответ написан
  • Что не так с webpack?

    @SuperOleg39ru
    Front-end разработчик
    Удалите babel-loader из конфига, точнее не добавляйте эту настройку в режиме разработки:
    {
            test: /\.(js|jsx)$/,
            exclude: /node_modules/,
            loader: 'babel',
            query: {
              cacheDirectory: true,
              plugins: ['transform-runtime', 'transform-decorators-legacy'],
              presets: ['es2015', 'react', 'stage-0']
            }
          }


    И не ленитесь изучать, как работает webpack, все окажется очень легко и понятно.
    Ответ написан
  • Как калькулятор, который написан на JQuery, засунуть в качестве компонента React?

    @SuperOleg39ru
    Front-end разработчик
    Если честно, не уверен что вы целенаправленно изучали реакт.
    Рекомендую потратить немного времени на этот курс: https://maxfarseer.gitbooks.io/react-course-ru/content/

    Небольшой пример на ES5:
    Для ограничения ввода, к примеру, возьмем готовый плагин react-numeric-input
    var NumericInput = require('react-numeric-input');
    
    var Calculator = React.createClass({
      getInitialState: function() {
        return {
          price: 0,
          offer: 0,
          result: 0
        };
      },
      caclResult: function() {
        this.setState({result: this.state.price - this.state.offer});
      },
      render: function() {
        return (
          <div className='calculator'>
            <NumericInput min={0} max={100} value={this.state.price} onChange={this.caclResult} />
            <NumericInput min={0} max={100} value={this.state.offer} onChange={this.caclResult} />
            <span>Итого: {this.state.result}</span>
          </div>
        )
      }
    });
    Ответ написан
    4 комментария