mirror of
https://github.com/status-im/react-native.git
synced 2025-02-03 21:24:31 +00:00
React Conf lanches
Reviewed By: ericvicenti, gfosco Differential Revision: D4679678 fbshipit-source-id: c1088390a44540e8934666e0ffdd43a3e170de32
This commit is contained in:
parent
3ce31c24da
commit
67a8d8951d
120
blog/2017-03-13-better-list-views.md
Normal file
120
blog/2017-03-13-better-list-views.md
Normal file
@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Better List Views in React Native
|
||||
author: Spencer Ahrens
|
||||
authorTitle: Software Engineer at Facebook
|
||||
authorURL: https://github.com/sahrens
|
||||
authorImage: https://avatars1.githubusercontent.com/u/1509831
|
||||
authorTwitter: sahrens2012
|
||||
category: engineering
|
||||
---
|
||||
|
||||
Many of you have started playing with some of our new List components already after our [teaser announcement in the community group](https://www.facebook.com/groups/react.native.community/permalink/921378591331053), but we are officially announcing them today! No more `ListView`s or `DataSource`s, stale rows, ignored bugs, or excessive memory consumption - with the latest React Native March 2017 release candidate (`0.43-rc.1`) you can pick from the new suite of components what best fits your use-case, with great perf and feature sets out of the box:
|
||||
|
||||
### [`<FlatList>`](https://facebook.github.io/react-native/releases/next/docs/flatlist.html) ###
|
||||
|
||||
This is the workhorse component for simple, performant lists. Provide an array of data and a `renderItem` function and you're good to go:
|
||||
|
||||
```
|
||||
<FlatList
|
||||
data={[{title: 'Title Text', key: 'item1'}, ...]}
|
||||
renderItem={({item}) => <ListItem title={item.title}}
|
||||
/>
|
||||
```
|
||||
|
||||
### [`<SectionList>`](https://facebook.github.io/react-native/releases/next/docs/sectionlist.html) ###
|
||||
|
||||
If you want to render a set of data broken into logical sections, maybe with section headers (e.g. in an alphabetical address book), and potentially with heterogeneous data and rendering (such as a profile view with some buttons followed by a composer, then a photo grid, then a friend grid, and finally a list of stories), this is the way to go.
|
||||
|
||||
```
|
||||
<SectionList
|
||||
renderItem={({item}) => <ListItem title={item.title}}
|
||||
renderSectionHeader={({section}) => <H1 title={section.key} />}
|
||||
sections={[ // homogenous rendering between sections
|
||||
{data: [...], key: ...},
|
||||
{data: [...], key: ...},
|
||||
{data: [...], key: ...},
|
||||
]}
|
||||
/>
|
||||
|
||||
<SectionList
|
||||
sections={[ // heterogeneous rendering between sections
|
||||
{data: [...], key: ..., renderItem: ...},
|
||||
{data: [...], key: ..., renderItem: ...},
|
||||
{data: [...], key: ..., renderItem: ...},
|
||||
]}
|
||||
/>
|
||||
```
|
||||
|
||||
### [`<VirtualizedList>`](https://facebook.github.io/react-native/releases/next/docs/virtualizedlist.html) ##
|
||||
|
||||
The implementation behind the scenes with a more flexible API. Especially handy if your data is not in a plain array (e.g. an immutable list).
|
||||
|
||||
## Features ##
|
||||
|
||||
Lists are used in many contexts, so we packed the new components full of features to handle the majority of use cases out of the box:
|
||||
|
||||
* Scroll loading (`onEndReached`).
|
||||
* Pull to refresh (`onRefresh` / `refreshing`).
|
||||
* [Configurable](https://github.com/facebook/react-native/blob/master/Libraries/CustomComponents/Lists/ViewabilityHelper.js) viewability (VPV) callbacks (`onViewableItemsChanged` / `viewabilityConfig`).
|
||||
* Horizontal mode (`horizontal`).
|
||||
* Intelligent item and section separators.
|
||||
* Multi-column support (`numColumns`)
|
||||
* `scrollToEnd`, `scrollToIndex`, and `scrollToItem`
|
||||
* Better Flow typing.
|
||||
|
||||
### Some Caveats ###
|
||||
|
||||
- The internal state of item subtrees is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay.
|
||||
|
||||
- These components are based on `PureComponent` which means that they will not re-render if `props` remains shallow-equal. Make sure that everything your `renderItem` function depends on directly is passed as a prop that is not `===` after updates, otherwise your UI may not update on changes. This includes the `data` prop and parent component state. For example:
|
||||
|
||||
```javascript
|
||||
<FlatList
|
||||
data={this.state.data}
|
||||
renderItem={({item}) => <MyItem
|
||||
item={item}
|
||||
onPress={() => this.setState((oldState) => ({
|
||||
selected: { // New instance breaks `===`
|
||||
...oldState.selected, // copy old data
|
||||
[item.key]: !oldState.selected[item.key], // toggle
|
||||
}}))
|
||||
}
|
||||
selected={
|
||||
!!this.state.selected[item.key] // renderItem depends on state
|
||||
}
|
||||
/>}
|
||||
selected={ // Can be any prop that doesn't collide with existing props
|
||||
this.state.selected // A change to selected should re-render FlatList
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously offscreen. This means it's possible to scroll faster than the fill rate and momentarily see blank content. This is a tradeoff that can be adjusted to suit the needs of each application, and we are working on improving it behind the scenes.
|
||||
|
||||
- By default, these new lists look for a `key` prop on each item and use that for the React key. Alternatively, you can provide a custom `keyExtractor` prop.
|
||||
|
||||
## Performance ##
|
||||
|
||||
Besides simplifying the API, the new list components also have significant performance enhancements, the main one being nearly constant memory usage for any number of rows. This is done by 'virtualizing' elements that are outside of the render window by completely unmounting them from the component hierarchy and reclaiming the JS memory from the react components, along with the native memory from the shadow tree and the UI views. This has a catch which is that internal component state will not be preserved, so **make sure you track any important state outside of the components themselves, e.g. in Relay or Redux or Flux store.**
|
||||
|
||||
Limiting the render window also reduces the amount of work that needs to be done by React and the native platform, e.g from view traversals. Even if you are rendering the last of a million elements, with these new lists there is no need to iterate through all those elements in order to render. You can even jump to the middle with `scrollToIndex` without excessive rendering.
|
||||
|
||||
We've also made some improvements with scheduling which should help with application responsiveness. Items at the edge of the render window are rendered infrequently and at a lower priority after any active gestures or animations or other interactions have completed.
|
||||
|
||||
## Advanced Usage ##
|
||||
|
||||
Unlike `ListView`, all items in the render window are re-rendered any time any props change. Often this is fine because the windowing reduces the number of items to a constant number, but if your items are on the complex side, you should make sure to follow React best practices for performance and use `React.PureComponent` and/or `shouldComponentUpdate` as appropriate within your components to limit re-renders of the recursive subtree.
|
||||
|
||||
If you can calculate the height of your rows without rendering them, you can improve the user experience by providing the `getItemLayout` prop. This makes it much smoother to scroll to specific items with e.g. `scrollToIndex`, and will improve the scroll indicator UI because the height of the content can be determined without rendering it.
|
||||
|
||||
If you have an alternative data type, like an immutable list, `<VirtualizedList>` is the way to go. It takes a `getItem` prop that lets you return the item data for any given index and has looser flow typing.
|
||||
|
||||
There are also a bunch of parameters you can tweak if you have an unusual use case. For example, you can use `windowSize` to trade off memory usage vs. user experience, `maxToRenderPerBatch` to adjust fill rate vs. responsiveness, `onEndReachedThreshold` to control when scroll loading happens, and more.
|
||||
|
||||
## Future Work ##
|
||||
|
||||
* Migration of existing surfaces (ultimately deprecation of `ListView`).
|
||||
* More features as we see/hear the need (let us know!).
|
||||
* Sticky section header support.
|
||||
* More performance optimizations.
|
||||
* Support functional item components with state.
|
48
blog/2017-03-13-idx-the-existential-function.md
Normal file
48
blog/2017-03-13-idx-the-existential-function.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: idx: The Existential Function
|
||||
author: Timothy Yung
|
||||
authorTitle: Engineering Manager at Facebook
|
||||
authorURL: https://github.com/yungsters
|
||||
authorImage: https://pbs.twimg.com/profile_images/1592444107/image.jpg
|
||||
authorTwitter: yungsters
|
||||
category: engineering
|
||||
---
|
||||
|
||||
At Facebook, we often need to access deeply nested values in data structures fetched with GraphQL. On the way to accessing these deeply nested values, it is common for one or more intermediate fields to be nullable. These intermediate fields may be null for a variety of reasons, from failed privacy checks to the mere fact that null happens to be the most flexible way to represent non-fatal errors.
|
||||
|
||||
Unfortunately, accessing these deeply nested values is currently tedious and verbose.
|
||||
|
||||
```javascript
|
||||
props.user &&
|
||||
props.user.friends &&
|
||||
props.user.friends[0] &&
|
||||
props.user.friends[0].friends
|
||||
```
|
||||
|
||||
There is [an ECMAScript proposal to introduce the existential operator](https://github.com/claudepache/es-optional-chaining) which will make this much more convenient. But until a time when that proposal is finalized, we want a solution that improves our quality of life, maintains existing language semantics, and encourages type safety with Flow.
|
||||
|
||||
We came up with an existential _function_ we call `idx`.
|
||||
|
||||
```javascript
|
||||
idx(props, _ => _.user.friends[0].friends)
|
||||
```
|
||||
|
||||
The invocation in this code snippet behaves similarly to the boolean expression in the code snippet above, except with significantly less repetition. The `idx` function takes exactly two arguments:
|
||||
|
||||
- Any value, typically an object or array into which you want to access a nested value.
|
||||
- A function that receives the first argument and accesses a nested value on it.
|
||||
|
||||
In theory, the `idx` function will try-catch errors that are the result of accessing properties on null or undefined. If such an error is caught, it will return either null or undefined. (And you can see how this might be implemented in [idx.js](https://github.com/facebookincubator/idx/blob/master/packages/idx/src/idx.js).)
|
||||
|
||||
In practice, try-catching every nested property access is slow, and differentiating between specific kinds of TypeErrors is fragile. To deal with these shortcomings, we created a Babel plugin that transforms the above `idx` invocation into the following expression:
|
||||
|
||||
```javascript
|
||||
props.user == null ? props.user :
|
||||
props.user.friends == null ? props.user.friends :
|
||||
props.user.friends[0] == null ? props.user.friends[0] :
|
||||
props.user.friends[0].friends
|
||||
```
|
||||
|
||||
Finally, we added a custom Flow type declaration for `idx` that allows the traversal in the second argument to be properly type-checked while permitting nested access on nullable properties.
|
||||
|
||||
The function, Babel plugin, and Flow declaration are now [available on GitHub](https://github.com/facebookincubator/idx). They are used by installing the **idx** and **babel-plugin-idx** npm packages, and adding “idx” to the list of plugins in your `.babelrc` file.
|
34
blog/2017-03-13-introducing-create-react-native-app.md
Normal file
34
blog/2017-03-13-introducing-create-react-native-app.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Introducing Create React Native App
|
||||
author: Adam Perry
|
||||
authorTitle: Software Engineer at Expo
|
||||
authorURL: https://github.com/dikaiosune
|
||||
authorImage: https://avatars2.githubusercontent.com/u/6812281
|
||||
authorTwitter: dika10sune
|
||||
category: engineering
|
||||
---
|
||||
|
||||
Today we’re announcing [Create React Native App](https://github.com/react-community/create-react-native-app): a new tool that makes it significantly easier to get started with a React Native project! It’s heavily inspired by the design of [Create React App](https://github.com/facebookincubator/create-react-app) and is the product of a collaboration between [Facebook](https://code.facebook.com) and [Expo](https://expo.io) (formerly Exponent).
|
||||
|
||||
Many developers struggle with installing and configuring React Native’s current native build dependencies, especially for Android. With Create React Native App, there’s no need to use Xcode or Android Studio, and you can develop for your iOS device using Linux or Windows. This is accomplished using the Expo app, which loads and runs CRNA projects written in pure JavaScript without compiling any native code.
|
||||
|
||||
Try creating a new project (replace with suitable yarn commands if you have it installed):
|
||||
|
||||
```
|
||||
$ npm i -g create-react-native-app
|
||||
$ create-react-native-app my-project
|
||||
$ cd my-project
|
||||
$ npm start
|
||||
```
|
||||
|
||||
This will start the React Native packager and print a QR code. Open it in the [Expo app](https://expo.io) to load your JavaScript. Calls to `console.log` are forwarded to your terminal. You can make use of any standard React Native APIs as well as the [Expo SDK](https://docs.expo.io/versions/latest/sdk/index.html).
|
||||
|
||||
## What about native code?
|
||||
|
||||
Many React Native projects have Java or Objective-C/Swift dependencies that need to be compiled. The Expo app does include APIs for camera, video, contacts, and more, and bundles popular libraries like [Airbnb’s react-native-maps](https://docs.expo.io/versions/v14.0.0/sdk/map-view.html), or [Facebook authentication](https://docs.expo.io/versions/latest/sdk/facebook.html). However if you need a native code dependency that Expo doesn’t bundle then you’ll probably need to have your own build configuration for it. Just like Create React App, “ejecting” is supported by CRNA.
|
||||
|
||||
You can run `npm run eject` to get a project very similar to what `react-native init` would generate. At that point you’ll need Xcode and/or Android Studio just as you would if you started with `react-native init` , adding libraries with `react-native link` will work, and you’ll have full control over the native code compilation process.
|
||||
|
||||
## Questions? Feedback?
|
||||
|
||||
Create React Native App is now stable enough for general use, which means we’re very eager to hear about your experience using it! You can find me [on Twitter](https://twitter.com/dika10sune) or open an issue on [the GitHub repository](https://github.com/react-community/create-react-native-app). Pull requests are very welcome!
|
Loading…
x
Reference in New Issue
Block a user