Skip to content

Commit 788d676

Browse files
yungsterselicwhite
andauthored
Remove PropTypes from native-components-ios.md (facebook#4190)
* Remove PropTypes from `native-components-ios.md` * Update native-components-ios.md export -> exports --------- Co-authored-by: Eli White <[email protected]>
1 parent a969fd8 commit 788d676

File tree

2 files changed

+158
-192
lines changed

2 files changed

+158
-192
lines changed

docs/native-components-ios.md

Lines changed: 79 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -57,36 +57,27 @@ Apple frameworks use two-letter prefixes, and React Native uses `RCT` as a prefi
5757
5858
Then you need a little bit of JavaScript to make this a usable React component:
5959
60-
```tsx title="MapView.tsx"
60+
```tsx {3} title="MapView.tsx"
6161
import {requireNativeComponent} from 'react-native';
6262
63-
// requireNativeComponent automatically resolves 'RNTMap' to 'RNTMapManager'
64-
module.exports = requireNativeComponent('RNTMap');
63+
export default requireNativeComponent('RNTMap');
6564
```
6665

66+
The `requireNativeComponent` function automatically resolves `RNTMap` to `RNTMapManager` and exports our native view for use in JavaScript.
67+
6768
```tsx title="MyApp.tsx"
6869
import MapView from './MapView.tsx';
6970

70-
...
71-
72-
render() {
71+
export default function MyApp() {
7372
return <MapView style={{flex: 1}} />;
7473
}
7574
```
7675

77-
Make sure to use `RNTMap` here. We want to require the manager here, which will expose the view of our manager for use in JavaScript.
78-
7976
:::note
8077
When rendering, don't forget to stretch the view, otherwise you'll be staring at a blank screen.
8178
:::
8279

83-
```tsx
84-
render() {
85-
return <MapView style={{flex: 1}} />;
86-
}
87-
```
88-
89-
This is now a fully-functioning native map view component in JavaScript, complete with pinch-zoom and other native gesture support. We can't really control it from JavaScript yet, though :(
80+
This is now a fully-functioning native map view component in JavaScript, complete with pinch-zoom and other native gesture support. We can't really control it from JavaScript yet, though.
9081

9182
## Properties
9283

@@ -98,36 +89,31 @@ RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
9889
9990
Note that we explicitly specify the type as `BOOL` - React Native uses `RCTConvert` under the hood to convert all sorts of different data types when talking over the bridge, and bad values will show convenient "RedBox" errors to let you know there is an issue ASAP. When things are straightforward like this, the whole implementation is taken care of for you by this macro.
10091
101-
Now to actually disable zooming, we set the property in JS:
92+
Now to actually disable zooming, we set the property in JavaScript:
10293
103-
```tsx title="MyApp.tsx"
104-
<MapView zoomEnabled={false} style={{flex: 1}} />
94+
```tsx {4} title="MyApp.tsx"
95+
import MapView from './MapView.tsx';
96+
97+
export default function MyApp() {
98+
return <MapView zoomEnabled={false} style={{flex: 1}} />;
99+
}
105100
```
106101

107-
To document the properties (and which values they accept) of our MapView component we'll add a wrapper component and document the interface with React `PropTypes`:
102+
To document the properties (and which values they accept) of our MapView component we'll add a wrapper component and document the interface with TypeScript:
108103

109-
```tsx title="MapView.tsx"
110-
import PropTypes from 'prop-types';
111-
import React from 'react';
104+
```tsx {6-9} title="MapView.tsx"
112105
import {requireNativeComponent} from 'react-native';
113106

114-
class MapView extends React.Component {
115-
render() {
116-
return <RNTMap {...this.props} />;
117-
}
118-
}
107+
const RNTMap = requireNativeComponent('RNTMap');
119108

120-
MapView.propTypes = {
109+
export default function MapView(props: {
121110
/**
122-
* A Boolean value that determines whether the user may use pinch
123-
* gestures to zoom in and out of the map.
111+
* Whether the user may use pinch gestures to zoom in and out.
124112
*/
125-
zoomEnabled: PropTypes.bool,
126-
};
127-
128-
const RNTMap = requireNativeComponent('RNTMap');
129-
130-
module.exports = MapView;
113+
zoomEnabled?: boolean;
114+
}) {
115+
return <RNTMap {...props} />;
116+
}
131117
```
132118

133119
Now we have a nicely documented wrapper component to work with.
@@ -186,41 +172,49 @@ You could write any conversion function you want for your view - here is the imp
186172
187173
These conversion functions are designed to safely process any JSON that the JS might throw at them by displaying "RedBox" errors and returning standard initialization values when missing keys or other developer errors are encountered.
188174
189-
To finish up support for the `region` prop, we need to document it in `propTypes`:
175+
To finish up support for the `region` prop, we can document it with TypeScript:
190176
191-
```tsx title="MapView.tsx"
192-
MapView.propTypes = {
193-
/**
194-
* A Boolean value that determines whether the user may use pinch
195-
* gestures to zoom in and out of the map.
196-
*/
197-
zoomEnabled: PropTypes.bool,
177+
```tsx {6-25} title="MapView.tsx"
178+
import {requireNativeComponent} from 'react-native';
179+
180+
const RNTMap = requireNativeComponent('RNTMap');
198181
182+
export default function MapView(props: {
199183
/**
200184
* The region to be displayed by the map.
201185
*
202186
* The region is defined by the center coordinates and the span of
203187
* coordinates to display.
204188
*/
205-
region: PropTypes.shape({
189+
region?: {
206190
/**
207191
* Coordinates for the center of the map.
208192
*/
209-
latitude: PropTypes.number.isRequired,
210-
longitude: PropTypes.number.isRequired,
193+
latitude: number;
194+
longitude: number;
211195
212196
/**
213197
* Distance between the minimum and the maximum latitude/longitude
214198
* to be displayed.
215199
*/
216-
latitudeDelta: PropTypes.number.isRequired,
217-
longitudeDelta: PropTypes.number.isRequired,
218-
}),
219-
};
200+
latitudeDelta: number;
201+
longitudeDelta: number;
202+
};
203+
/**
204+
* Whether the user may use pinch gestures to zoom in and out.
205+
*/
206+
zoomEnabled?: boolean;
207+
}) {
208+
return <RNTMap {...props} />;
209+
}
220210
```
221211

222-
```tsx title="MyApp.tsx"
223-
render() {
212+
We can now supply the `region` prop to `MapView`:
213+
214+
```tsx {4-9,12} title="MyApp.tsx"
215+
import MapView from './MapView.tsx';
216+
217+
export default function MyApp() {
224218
const region = {
225219
latitude: 37.48,
226220
longitude: -122.16,
@@ -237,8 +231,6 @@ render() {
237231
}
238232
```
239233

240-
Here you can see that the shape of the region is explicit in the JS documentation.
241-
242234
## Events
243235

244236
So now we have a native map component that we can control freely from JS, but how do we deal with events from the user, like pinch-zooms or panning to change the visible region?
@@ -319,55 +311,46 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
319311
320312
In the delegate method `-mapView:regionDidChangeAnimated:` the event handler block is called on the corresponding view with the region data. Calling the `onRegionChange` event handler block results in calling the same callback prop in JavaScript. This callback is invoked with the raw event, which we typically process in the wrapper component to simplify the API:
321313
322-
```tsx title="MapView.tsx"
323-
class MapView extends React.Component {
324-
_onRegionChange = event => {
325-
if (!this.props.onRegionChange) {
326-
return;
327-
}
314+
```tsx {3-10,14-17,19} title="MapView.tsx"
315+
// ...
328316
329-
// process raw event...
330-
this.props.onRegionChange(event.nativeEvent);
317+
type RegionChangeEvent = {
318+
nativeEvent: {
319+
latitude: number;
320+
longitude: number;
321+
latitudeDelta: number;
322+
longitudeDelta: number;
331323
};
332-
render() {
333-
return (
334-
<RNTMap
335-
{...this.props}
336-
onRegionChange={this._onRegionChange}
337-
/>
338-
);
339-
}
340-
}
341-
MapView.propTypes = {
324+
};
325+
326+
export default function MapView(props: {
327+
// ...
342328
/**
343329
* Callback that is called continuously when the user is dragging the map.
344330
*/
345-
onRegionChange: PropTypes.func,
346-
...
347-
};
331+
onRegionChange: (event: RegionChangeEvent) => unknown;
332+
}) {
333+
return <RNTMap {...props} onRegionChange={onRegionChange} />;
334+
}
348335
```
349336

350-
```tsx title="MyApp.tsx"
351-
class MyApp extends React.Component {
352-
onRegionChange(event) {
353-
// Do stuff with event.region.latitude, etc.
354-
}
337+
```tsx {6-9,14} title="MyApp.tsx"
338+
import MapView from './MapView.tsx';
355339

356-
render() {
357-
const region = {
358-
latitude: 37.48,
359-
longitude: -122.16,
360-
latitudeDelta: 0.1,
361-
longitudeDelta: 0.1,
362-
};
363-
return (
364-
<MapView
365-
region={region}
366-
zoomEnabled={false}
367-
onRegionChange={this.onRegionChange}
368-
/>
369-
);
370-
}
340+
export default function MyApp() {
341+
// ...
342+
343+
const onRegionChange = useCallback(event => {
344+
const {region} = event.nativeEvent;
345+
// Do something with `region.latitude`, etc.
346+
});
347+
348+
return (
349+
<MapView
350+
// ...
351+
onRegionChange={onRegionChange}
352+
/>
353+
);
371354
}
372355
```
373356

0 commit comments

Comments
 (0)