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

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.

主站蜘蛛池模板: 石泉县| 安岳县| 九江市| 翁牛特旗| 固镇县| 泰和县| 无为县| 宝山区| 瓦房店市| 阿坝| 宁南县| 临武县| 阜南县| 含山县| 河间市| 绩溪县| 城固县| 揭东县| 婺源县| 沧源| 广昌县| 区。| 县级市| 黄冈市| 普兰店市| 通江县| 高州市| 永寿县| 涞水县| 潜江市| 铁力市| 郁南县| 工布江达县| 南澳县| 蒙自县| 晋中市| 诏安县| 三明市| 龙海市| 九江市| 华容县|