Home » Blog » Dev notes » Magento on React

Magento on React

thumbnail

GET ALL YOU CAN OUT OF MAGENTO IN 21ST CENTURY

These days, Javascript is probably the most dynamic and rapidly developing programming language. Despite no canonical class creation, scope bindings, and weird equality bugs (who’d remember about it anyway), it’s the most commonly used one. Still don’t believe it? Check Stack Overflow.

A lot of front-end developers claim that Magento is outdated and practically worthless. Are they right?

The real key to access the JS frameworks heaven is REST API. While our e-commerce platform provides it…its access is restricted mostly to actions undertaken from admin dashboard. To bypass this obstacle, a bunch of developers had joined forces and finally presented MoA: Magento on Angular: https://github.com/Wildhoney/Magento-on-Angular

Sadly, the last commit was posted more than a year ago, on June 30th, 2015. Furthermore, the 14th of September 2016 was the official release date of Angular 2. So… is it still a good idea to use Angular1?

In the middle of Angular vs React battle, here comes our crew with the solution: Magento on React-Redux.

In a nutshell, React is JS library allowing you to build Single Page Applications with reusable components. You can find more examples here: https://facebook.github.io/react/. Redux works extremely well with React library, and it helps storing the current state of the application in “store” (any resemblance to store word is <> coincidental).

In Magento store, it would be perfect to be able to collect data like qty in cart or user data. So let me explain the very basics:

We have three separate VirtualHosts:

  • One for magento: magento.moa.localhost/
  • One for Laravel: api.moa.localhost/
  • One for Our React instance: moa.localhost/

MoA provides REST API by using Laravel to get informations from Magento like: Categories, Products, Accounts, etc.

Let’s leave backend and talk about frontend a bit. Our goal is to fetch the products list.

First, we have declaration of routes:

<Provider store={store}>
  <Router history={history}>
    <Route path="/" component={Main}>
      <IndexRoute component={Home}></IndexRoute>
      <Route path='/product' component={Products}></Route>
      <Route path='/product/:id' component={Product}></Route>
    </Route>
  </Router>
</Provider>

In oposite of normal Flux approach we have only one store which is connected to Provider component

Each route is represented by <Route>, especially <IndexRoute> which leads to default address

class Products extends React.Component {
  constructor(props) {
  super(props);
}
  componentDidMount() {
  const { dispatch } = this.props;
  dispatch(productsAction.fetchProducts());
}
  render() {
  const {isFetching, products} = this.props.products;
  return (
  >section className='products'>
  {!isFetching && (products.length > 0) ?
      products.map( (product, i) => >Link to={`/product/${product.id}`}>>ProductThumb {...product}/>>/Link>) :
      >p>Loading>/p>}
  >/section>
  )
}
}
  function mapStateToProps(state) {
    return {
    routing: state.routing,
    products: state.products
  }
  }
  export default connect(mapStateToProps)(Products);

Products component is Container, which:

  • on componentDidMount try to get list with action: productsAction.fetchProducts()
  • after success show the sequent products in .map function
  • connect to store data with: connect(mapStateToProps)(Products);

Here is our fetch action:

export function fetchProducts() {
  return dispatch => {
  dispatch(requestProducts());
  return fetch(`http://api.moa.localhost/products`, {
  mode: 'cors'
})
  .then(response => response.text())
  .then(json => dispatch(receiveProducts(JSON.parse(json))))
}
}
  function requestProducts() {
    return {
    type: REQUEST_PRODUCTS
  }
  }
  function receiveProducts(products) {
    return {
    type: RECEIVE_PRODUCTS,
    products: products
  }
  }

REQUEST_PRODUCTS and RECEIVE_PRODUCTS are string constants, imported from another module. Firstly, we inform our store that we are asynchronous fetching data (to put some overlay, etc.) When the data arrives, we pass our products to reducer:

const initialState = {
  isFetching: false,
  products: []
};
export function products(state = initialState, action) {
    switch (action.type){
    case REQUEST_PRODUCTS: {
    return Object.assign({}, state, {
    isFetching: true
  });
  }
    case RECEIVE_PRODUCTS: {
    return Object.assign({}, state, {
    isFetching: false,
    products: action.products
  });
  }
    default:
    return state;
  }
  }

Each time we trigger a reducer, the state of store is updated.


However, after one day of tests, I can state the following cons of using MoA (or rather MoR):

  • API doesn’t work correctly, I couldn’t get proper values of categories
  • It’s time-consuming: to build the whole e-shop, we would have to build our own UI
  • Why bother? In Magento 2 there is out-of-the-box REST API

To sum up, I think that MoA is an interesting project, but only to build some hobby-purposed shops.
E-commerce platforms are too huge to be created instantly. The REST API will only be open for us in all its glory in Magento 2.

+1 (4 votes, average: 5.00 out of 1)
Loading...

Leave a Reply

Your email address will not be published. Required fields are marked *

*