官术网_书友最值得收藏!

Stateless and stateful components

First of all, let's look at the first stateless component that has been created for us. It has been automatically generated by Create React Native App (CRNA) for our Hello World application. This component was created using the class syntax that was introduced in ECMAScript 2015 (ES6). Such components are usually called class components:

// src/ Chapter 1/ Example 1_Hello World/ App.js

export default class
App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Hands-On Design Patterns with React Native</Text>
<Text>Chapter 1: React Component Patterns</Text>
<Text style={styles.text}>You are ready to start the journey.
Fun fact is, this text is rendered by class component called
App. Check App.js if you want to look it up.</Text>
</View>
);
}

}

Class components can be used to create stateful components.

The code samples provided in this book use ECMAScript 2018 syntax with Stage 3 feature  class field declarations . Babel is the transpiler that supports such code by relevant plugins th at are pre-configured for us by the CRNA toolbox. If you decide not to use CRNA, then you may need to configure Babel yourself.

However, in this case, the class component is unnecessary. We can safely use a stateless one, as it's simpler. Let's see how we can declare a stateless component. The most common approach is by using ES6 arrow syntax. Such components are called functional components. Check out the following code to see what our rewritten component looks like:

const App = () => (
<View style={styles.container}>
<Text>Hands-On Design Patterns with React Native</Text>
<Text>Chapter 1: React Component Patterns</Text>
<Text style={styles.text}>You are ready to start the journey. Fun
fact is, this text is rendered by Functional Component called
App. Check App.js if you want to look it up.</Text>
</View>
);
export default App;

If you are not a fan of arrow syntax, you can also use regular function syntax:

// src/ Chapter 1/ Example_2_Functional_Components/ App.js

export default function
App() {
return (
<View style={styles.container}>
...
</View>
);
}

The very first question that pop ups is: why is it stateless? The answer is simple: it doesn't contain any inner state. This means that we are not storing any private data inside it. Everything the component needs to render itself is provided from the external world, which the component does not care about.

In this little example, we actually never pass any external data to the component. Let's do that now. To do so, we will create another component called HelloText that consumes one property: text to display. The usual convention to pass the text to such a component is to place the text between the opening and closing tag, for instance, <HelloText> example text that is passed </HelloText>. Hence, to retrieve such a prop within our functional component, we will need to use a special key called children:

// src/ Chapter 1/ Example_3_Functional_Components_with_props/ App.js

const
HelloText = ({children, ...otherProps}) => (
<Text {...otherProps}>{children}</Text>
);
const App = () => (
<View style={styles.container}>
<HelloText>
Hands-On Design Patterns with React Native
</HelloText>
<HelloText>Chapter 1: React Component Patterns</HelloText>
<HelloText style={styles.text}>
You are ready to start the journey. Fun fact is, this text
is rendered by Functional Component called HelloText.
Check App.js if you want to look it up.
</HelloText>
</View>
);
export default App;

Using the children prop makes our HelloText component way more powerful. Props are a very flexible mechanism. Using props, you can send any valid JavaScript type. In this case, we have sent just text, but you can send other components, too.

It's time to add some vitality to our component. We will make it expand the third text block, but only after pressing the chapter or title text. For this functionality, we need to store a state that remembers if the component is expanded or collapsed.

Here is what you need to do:

  1. Change the component to the class syntax.
  2. Leverage the state object of the React library. We must initialize the state within the class constructor and make the text collapsed by default.
  3. Add conditional rendering to the component render function.
  4. Add the press handler, which will change the state once we tap on the title or chapter text.

The solution is presented in the following code:

// src/ Chapter 1/ Example_4_Stateful_expandable_component/ App.js

export default class App extends React.Component {
constructor() {
super();
this.state = {
// default state on first render
expanded:
false
}
}

expandOrCollapse() {
// toggle expanded: true becomes false, false becomes true
this.setState({expanded: !this.state.expanded})
;
}

render = () => (
<View style={styles.container}>
<HelloText onPress={() => this.expandOrCollapse()}>
Hands-On Design Patterns with React Native
</HelloText>
<HelloText onPress={() => this.expandOrCollapse()}>
Chapter 1: React Component Patterns
</HelloText>
{
this.state.expanded &&
<HelloText style={styles.text}>
You can expand and collapse this text by clicking
the Title or Chapter text. Bonus: Check Chapter 4
to learn how to animate expanding andcollapsing.
</HelloText>
}
</View>
);
}

Congratulations—we have made our first stateless and stateful components!

Note the  && operator that displays the component. If a Boolean value on the left side of the operator is true, then the component on the right-hand side will be displayed. The whole expression needs to be wrapped into curly brackets. We will explore more of its capabilities in Chapter 3, Style Patterns.

It's time to create something more challenging: Task list. Please start over and prepare your code. Clean up App.js so that it only includes the App class component:

  1. The constructor should initialize the task list in its state. In my example, the task list will be an array of strings.
  2. Iterate over the tasks to create the Text component for each task. This should happen in the render function of the App component. Please note that you can simplify iteration by using the map function instead of a regular for loop. Doing this should become second nature, since it's became a standard in almost every JS project.

My solution is presented in the following code:

// src/ Chapter 1/ Example 5_Task_list/ App.js

export default class App extends React.Component {
constructor() {
super();
// Set the initial state, tasks is an array of strings
this.state = {
tasks: ['123', '456']
}
}

render = () => (
<View style={styles.container}>
{
this.state.tasks
.map((task, index) => (

<Text key={index} style={styles.text}>{task}</Text>
))

}
</View>
);
}

Iterating using map is a nice feature, but the whole component doesn't look like a task list yet. Don't worry, you will learn how to style components in Chapter 3, Style Patterns.

主站蜘蛛池模板: 常州市| 石狮市| 紫阳县| 邹平县| 青阳县| 凉山| 惠东县| 蚌埠市| 香格里拉县| 石屏县| 广昌县| 拉孜县| 铜陵市| 利川市| 刚察县| 怀集县| 玉林市| 屏东市| 潜山县| 岳阳市| 弥渡县| 西藏| 大安市| 湖口县| 金华市| 长兴县| 越西县| 高尔夫| 集安市| 长垣县| 长泰县| 大名县| 深州市| 黄浦区| 中方县| 威信县| 富平县| 澄江县| 高州市| 宁海县| 灵石县|