M
M
Maxim Gatilin2017-05-23 16:40:03
Frontend
Maxim Gatilin, 2017-05-23 16:40:03

Can you comment on a React/Redux app?

Hi all.
I made my first React/Redux app and am looking for any feedback (code, design).
The application displays the user's current weather (you can change the location).
Github
Application

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
Islam Ibakaev, 2017-05-26
@gatilin222

1) you can use the spread operator out of the box

case 'SWITCH_EDIT_MODE':
      return Object.assign({}, state, {
        editMode: action.value
      })

case 'SWITCH_EDIT_MODE':
      return { ...state, editMode: action.value}

2) weatherApiIdhide in .envand .envthrow in .gitignore( dotenv-webpack to the rescue)
3) MainContainerin my opinion
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from './../../actions/actionCreators';
import Main from './../Main/Main';

class MainContainer extends React.Component {

  componentDidMount() {
    this.props.actions.detectLocation();
  }

  render() {
  	return <Main {...this.props.store}  {...this.props.actions} />
  }
}

const mapStateToProps = state => ({ store: state })
const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actionCreators, dispatch) })

export default connect(mapStateToProps, mapDispatchToProps)(MainContainer)

and Mainaccordingly
import React from 'react';
import PropTypes from 'prop-types';

import styles from './Main.css';

import PageBackground from './../PageBackground/PageBackground';
import WeatherIcon from './../WeatherIcon/WeatherIcon';
import Temperature from './../Temperature/Temperature';
import Location from './../Location/Location';
import Loader from './../Loader/Loader';
import Error from './../Error/Error';

const propTypes = {
  pageBackground: PropTypes.string,
  location: PropTypes.object,
  editMode: PropTypes.bool,
  changeLocation: PropTypes.func,
  switchEditMode: PropTypes.func,
  weatherIcon: PropTypes.string,
  temperature: PropTypes.number,
  weatherDescription: PropTypes.string
};

export default function Main (props) {
  return (
    <div className={styles.container}>
      {props.loading && <Loader />}
      {props.loadingError && <Error>Sorry, an error occurred. Try to reload page</Error>}
      <PageBackground background={props.pageBackground} />
      <Location city={props.location.city}
        editMode={props.editMode}
        onLocationSelect={props.changeLocation}
        onChangeLocationClick={() => props.switchEditMode(true)}
        onInputBlur={() => props.switchEditMode(false)} />
      <div className={styles.split}>
       <WeatherIcon code={props.weatherIcon} class={styles.icon}/>
      	<span className={styles.date}>Today</span>
      </div>
      <Temperature value={props.temperature}/>
      <div className={styles.description}>props.weatherDescription}</div>
    </div>
  )
}

Main.propTypes = propTypes;

4) Ideally, all but components MainContainershould (in this project) be functional components.
5) it would be possible to write more reducers (separate for getting location, for weather, for pagebackground) this would allow you to "squeeze out" logic from child components (PageBackground, Temperature, WeatherIcon) in MainContainerorder to present it in a functional form
6) you need to limit the number -requests for a certain period of time (for example, 15 minutes), because the weather does not change so often ( express-rate-limit ).

A
Alexander Manakov, 2017-05-23
@gogolor

Cool design)))
I came across a small jamb in the code

fetchJsonp(...)
.then(response => response.json(), error => {dispatch(loadingFailed())})
.then(weather => dispatch(receiveWeather(weather)));

If your fetchJsonp crashes, then dispatch(loadingFailed()), but after that it still goes to dispatch(receiveWeather(weather)), where weather is undefined =(

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question