Subscribe now

Stateless Components [12.21.2016]

We're going to talk about Stateless components today. In the React architecture, you would think React is the V in MVC, right ? No. Actually, React is the V and C. Dan Abramov explains it very well dividing all the components in presentational components and containers. Let's take a look:

Presentational, dumb or pure/stateless components: - Are concerned how things look - Don't specify how data is muted - Don't have state

Container Components, smart or stateful components: - Are concerned how things work - Call Flux/Redux actions - They normally have state, because they are normalling working as data sources

There is a lot of content about that on the internet, but before diving into the code, let's take a look at how Stateless components can help us.

1. Easy to test Since we have a straightforward and simple component without state - anything changes. The component will always return the same thing for us, based on props. So, for testing we just need to pass props and see what the component returns.

2. Easy to understand If you look at a stateless component you will easily figure out what it does: normally it doesn't have a state and it doesn't have much code inside. For example: If you have a stateless component always returning the same tags and printing Hello World, you can easily understand what this component does.

3. Enforce Best Practices If you divide your components into dumb/smart components you probably have a good division and a well structured code. This is good, not ?

4. Refactoring purposes If you want to refactor your code later and if you have divided the code using this standard, it will be easier to refactor. Afterwards, if you use some state library, like redux, it will be easier to add.

Now, let's make a prototype of an app, just using stateless components. But why? Because, it's very simple and we just need to pass props. Props will be our content.

You can find the entire code in our github in the following link.

Our application has two screens, the first screen will be a list of all the React Native documentation and the second screen will be the content.

At the index.ios.js we will have a navigator with our two routes. As screens we will have Main and DetailsDocs.

Main contains our List and Details should contains the component description. We're passing as initialRoute the Main component where the key is first.

function navigatorRenderScene(route, navigator) {
  switch (route.index) {
    case 'first':
      return (<Main navigator={navigator} title="Main Screen" />);
    case 'details':
      return (<DetailsDocs navigator={navigator} title="Details Docs" />);
  }
}

const reactNativeDocs = () => {
  return (<Navigator
        initialRoute={{ index: 'first' }}
        renderScene={navigatorRenderScene}
      />);
}

Our reactNativeDocs is a stateless component.

Let's check the Main component. It is a stateless component, we're receiving the props, in this case is the props from navigator, where we are passing to the ListDocs. Look at this component and see that just looking at the first time you can figure out what it does.

const Main = (props) => {
  return (
    <View style={styles.container}>
      <View>
        <Text style={styles.main}>
          React Native Documentation
        </Text>
        <ListDocs navigator={props.navigator} />
      </View>
    </View>
  );
}

Let's check our ListDocs. Our ListDocs is a simple Listview implementation. We already saw a similar code when we were studying about ListViews, so this code should be familiar to you. Here, we're passing some fake data to our data source and this is t a stateless component.


export default class ListDocs extends Component {

  constructor(props) {
    super(props);
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: ds.cloneWithRows([
        'TouchableHighlight', 'Image', 'Network', 'Text', 'StyleSheet', 'View', 'ListView', 'Component'
      ])
    };

    this.onClickList = this.onClickList.bind(this);
  }

  onClickList(rowData){
    this.props.navigator.push({
      index: 'details',
      data: rowData
    })
  }

  render() {
    return (
      <View style={styles.container}>
        <View>
          <ListView
            dataSource={this.state.dataSource}
            renderRow={(rowData) =>
              <TouchableHighlight underlayColor='white' onPress={this.onClickList.bind(null, rowData)}>
              <View>
                <Text>Docs</Text>
                <Text style={styles.textComponent}>{rowData}</Text>
              </View>
              </TouchableHighlight>
            }
          />
        </View>
      </View>
    );
  }
}

Let's go back to our main screen and check the second route we have,let's see our DetailsDocs. Here we are not passing anything. Just showing a static text. This is also a stateless component.

const DetailsDocs = () => {
  return (
    <View style={styles.container}>
      <Text>Details Docs</Text>
    </View>
    );
}

The only component using state here is our ListDocs, because we need the state for the ListView component. One of the good things about using stateless components is that it helps us to structure our project.

As we said, Stateless components have some benefits and it's worth using those. Next time you are going to create a component, be careful before starting to write a class.

Resources