Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mern.io scaffolder tool - What is the .need method all about?

Based on the scaffolder mern.io I was going through the code to see what was going on. I stumbled upon a .need method which looks like something related to es6 classes. I can't seem to find any usable info anywhere, so I ask what is the .need method?

class PostContainer extends Component {
   //do class setup stuff here
}

PostContainer.need = [() => { return Actions.fetchPosts(); }];

You can get the project up and running very easily with these commands.

npm install -g mern-cli
mern YourAppName
like image 280
Sten Muchow Avatar asked Feb 24 '16 22:02

Sten Muchow


1 Answers

The mern documentation is pretty terse when it comes to explaining this.

fetchComponentData collects all the needs (need is an array of actions that are required to be dispatched before rendering the component) of components in the current route. It returns a promise when all the required actions are dispatched.

Reading through the code is a much clearer way of finding out what's going on here.

Overview

It's a way to specify some actions that should be dispatched before rendering the component.

This component maps the posts property from the Redux store to a prop called posts so that it can render the list of posts.

// PostContainer.jsx
function mapStateToProps(store) {
  return {
    posts: store.posts,
  };
}

However, initially this property will be empty because the posts need to be fetched from an asynchronous API.

// reducer.js
// initial state of the store is an empty array
const initialState = { posts: [], selectedPost: null };

This component needs the posts to be available before it renders, so it dispatches the action returned from the call to Actions.fetchPosts().

// actions.js
export function fetchPosts() {
  return (dispatch) => {
    return fetch(`${baseURL}/api/getPosts`).
      then((response) => response.json()).
      then((response) => dispatch(addPosts(response.posts)));
  };
}

When the action has finished dispatching, the store's data can be mapped to the connected component.

Caveat

This isn't a universal way to specify asynchronous dependencies for React components. It only works because mern has a utility method called fetchComponentData that it calls at the server side, in order to populate the Redux store before rendering.

// server.js
fetchComponentData(store.dispatch, renderProps.components, renderProps.params)

This method traverses the components from the second argument to extract the needs from each. Then it executes 'needs` and waits for all the promises to complete.

// fetchData.js
const promises = needs.map(need => dispatch(need(params)));
return Promise.all(promises);

When the promise returned by Promise.all(promise) completes, the Redux store will be populated and the components can safely render their data to be served to the client.

Syntax

You mentioned that you thought it might be related to ES6 classes, so I'll cover the syntax quickly too.

ES6 classes can't have static properties specified in the class literal, instead we have to declare them as properties on the class after it has been defined.

The needs property must be an array of functions that return promises to work with fetchComponentData. In this case we have an arrow function declared inside an array literal. It might help to look at it split up into separate variables.

const fetchPosts = () => { return Actions.fetchPosts() };
const needs = [fetchPosts];
PostContainer.need = needs;
like image 125
Dan Prince Avatar answered Oct 07 '22 10:10

Dan Prince