diff --git a/README.md b/README.md index 7f0df7d..19d06a7 100755 --- a/README.md +++ b/README.md @@ -182,44 +182,48 @@ in [Editable Complex Components](#editable-complex-components). ![demo-3](./.github/large-network-example.gif) ```jsx -state = { - loading: true, - users: [], -} - -async componentWillMount() { - const response = await fetch('https://randomuser.me/api/?results=5000') - const data = await response.json() - - this.setState({ - loading: false, - users: data.results.map(a => ({ - name: `${a.name.first} ${a.name.last}`, - id: a.registered, - })), - }) -} +() => { + const [loading, setLoading] = useState(true); + const [users, setUsers] = useState([]); + + useEffect(() => { + const getUsers = async () => { + const response = await fetch('https://randomuser.me/api/?results=5000'); + const data = await response.json(); + + setLoading(false); + setUsers( + data.results.map(a => ({ + name: `${a.name.first} ${a.name.last}`, + id: a.registered, + })) + ); + }; + + getUsers(); + }, []); -render() { return ( - {this.state.loading ? 'Fetching' : 'Fetched'} 5000 users + {loading ? 'Fetching' : 'Fetched'} 5000 users - {this.state.loading && } + {loading && }
- {this.state.users.map(a => {a.name})} + {users.map(a => ( + {a.name} + ))}
- ) -} + ); +}; ``` ### App-bundled JSON with filter and selected value checkmarked @@ -256,7 +260,7 @@ render() {
Item 1 @@ -279,59 +283,84 @@ render() { ![pull to refresh example](./.github/pull-to-refresh-example.gif) ```jsx -state = { - loading: true, - users: [], - refreshing: false, - amount: 10, +function reducer(state, action) { + switch (action.type) { + case 'getUsers': + return { ...state, loading: false, users: action.payload }; + case 'startRefresh': + return { ...state, refreshing: true }; + case 'endRefresh': + return { + ...state, + refreshing: false, + amount: state.amount + 10, + users: [...state.users, ...action.payload], + }; + default: + return state; + } } -async componentWillMount() { - const users = await this.fetchUsers() +() => { + const [{ loading, amount, refreshing, users }, dispatch] = useReducer( + reducer, + { + loading: true, + users: [], + refreshing: false, + amount: 10, + } + ); - this.setState({ - loading: false, - users, - }) -} + useEffect(() => { + const getUsers = async () => { + const data = await fetchUsers(); + dispatch({ type: 'getUsers', payload: data }); + }; -fetchUsers = async () => { - const response = await fetch('https://randomuser.me/api/?results=10') - const data = await response.json() + getUsers(); + }, []); - return data.results.map(a => ({ - name: `${a.name.first} ${a.name.last}`, - id: a.registered, - })) -} + const fetchUsers = async () => { + const response = await fetch('https://randomuser.me/api/?results=10'); + const data = await response.json(); -fetchMore = () => { - this.setState({ refreshing: true }, async () => { - const users = await this.fetchUsers() - this.setState({ users: [...users, ...this.state.users], refreshing: false, amount: this.state.amount + 10 }) - }) -} + return data.results.map(a => ({ + name: `${a.name.first} ${a.name.last}`, + id: a.login.uuid, + })); + }; + + const fetchMore = async () => { + dispatch({ type: 'startRefresh' }); + const data = await fetchUsers(); + dispatch({ type: 'endRefresh', payload: data }); + }; -render() { return ( - {this.state.loading ? 'Fetching' : 'Fetched'} {this.state.amount} users + {loading ? 'Fetching' : 'Fetched'} {amount} users - {this.state.loading && } + {loading && } -
{this.state.users.map(a => {a.name})}
+
+ {users.map(a => ( + {a.name} + ))} +
- ) + ); +}; } ``` @@ -395,14 +424,14 @@ An `image` prop can be a string pointing to the name of an asset in your "Asset Catalog". In this case an `imageWidth` prop is recommended. ```jsx -; + ``` Alternatively, you can `require` the image from your local app code. In this case an `imageWidth` is unnecessary. ```jsx -; + ``` ### Editable Complex Components @@ -492,7 +521,7 @@ For more examples, see examples/TableViewDemo. /> ); })} -
; + ``` Note that the props you pass must be primitive types: they cannot be objects. diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 83cd483..7d2808e 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -138,6 +138,7 @@ android { } dependencies { + implementation project(':react-native-reanimated') implementation project(':react-native-gesture-handler') implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" diff --git a/example/android/app/src/main/java/com/tableviewdemo/MainActivity.java b/example/android/app/src/main/java/com/tableviewdemo/MainActivity.java index 60c6a05..d82922e 100644 --- a/example/android/app/src/main/java/com/tableviewdemo/MainActivity.java +++ b/example/android/app/src/main/java/com/tableviewdemo/MainActivity.java @@ -1,6 +1,9 @@ package com.tableviewdemo; import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.ReactRootView; +import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; public class MainActivity extends ReactActivity { @@ -12,4 +15,14 @@ public class MainActivity extends ReactActivity { protected String getMainComponentName() { return "TableViewDemo"; } + + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new ReactActivityDelegate(this, getMainComponentName()) { + @Override + protected ReactRootView createRootView() { + return new RNGestureHandlerEnabledRootView(MainActivity.this); + } + }; + } } diff --git a/example/android/app/src/main/java/com/tableviewdemo/MainApplication.java b/example/android/app/src/main/java/com/tableviewdemo/MainApplication.java index 3436e47..c82da77 100644 --- a/example/android/app/src/main/java/com/tableviewdemo/MainApplication.java +++ b/example/android/app/src/main/java/com/tableviewdemo/MainApplication.java @@ -3,6 +3,7 @@ import android.app.Application; import com.facebook.react.ReactApplication; +import com.swmansion.reanimated.ReanimatedPackage; import com.swmansion.gesturehandler.react.RNGestureHandlerPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; @@ -24,6 +25,7 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new ReanimatedPackage(), new RNGestureHandlerPackage() ); } diff --git a/example/android/settings.gradle b/example/android/settings.gradle index d1b6dfe..9684d07 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'TableViewDemo' +include ':react-native-reanimated' +project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android') include ':react-native-gesture-handler' project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android') diff --git a/example/ios/TableViewDemo.xcodeproj/project.pbxproj b/example/ios/TableViewDemo.xcodeproj/project.pbxproj index acd754b..1585066 100644 --- a/example/ios/TableViewDemo.xcodeproj/project.pbxproj +++ b/example/ios/TableViewDemo.xcodeproj/project.pbxproj @@ -5,7 +5,6 @@ }; objectVersion = 46; objects = { - /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; @@ -44,6 +43,8 @@ DD2510CA1A414BE49C49BA99 /* libRNTableView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C235EA15AC0845A9BF9BBD05 /* libRNTableView.a */; }; ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED297162215061F000B7C4FE /* JavaScriptCore.framework */; }; ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2971642150620600B7C4FE /* JavaScriptCore.framework */; }; + 95AFB2FD224842F6BA9FD783 /* libRNReanimated.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A5C64E19BFC74D85AB6986AD /* libRNReanimated.a */; }; + 4AD036883BD6449584E7B380 /* libRNReanimated-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FC810FCC3B2F43BC9516842A /* libRNReanimated-tvOS.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -378,6 +379,9 @@ EB9353B6ACA54416963EA1E5 /* RNTableView.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNTableView.xcodeproj; path = "../node_modules/react-native-tableview/RNTableView.xcodeproj"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; + 2EF53D72C8B446C4A300FBC6 /* RNReanimated.xcodeproj */ = {isa = PBXFileReference; name = "RNReanimated.xcodeproj"; path = "../node_modules/react-native-reanimated/ios/RNReanimated.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + A5C64E19BFC74D85AB6986AD /* libRNReanimated.a */ = {isa = PBXFileReference; name = "libRNReanimated.a"; path = "libRNReanimated.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + FC810FCC3B2F43BC9516842A /* libRNReanimated-tvOS.a */ = {isa = PBXFileReference; name = "libRNReanimated-tvOS.a"; path = "libRNReanimated-tvOS.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -408,6 +412,7 @@ 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, DD2510CA1A414BE49C49BA99 /* libRNTableView.a in Frameworks */, D1BF78E1D34643189115AF19 /* libRNGestureHandler.a in Frameworks */, + 95AFB2FD224842F6BA9FD783 /* libRNReanimated.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -425,6 +430,7 @@ 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */, 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */, 030A481EB7B34BBAA3FC26EE /* libRNGestureHandler-tvOS.a in Frameworks */, + 4AD036883BD6449584E7B380 /* libRNReanimated-tvOS.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -628,6 +634,7 @@ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, EB9353B6ACA54416963EA1E5 /* RNTableView.xcodeproj */, 036FDCC3112D4CB186BD3FAD /* RNGestureHandler.xcodeproj */, + 2EF53D72C8B446C4A300FBC6 /* RNReanimated.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -1279,6 +1286,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = TableViewDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1288,6 +1296,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1308,6 +1318,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = TableViewDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1317,6 +1328,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1338,6 +1351,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = TableViewDemo/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1361,6 +1375,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = TableViewDemo/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1391,6 +1406,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = "TableViewDemo-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1399,6 +1415,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1428,6 +1446,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = "TableViewDemo-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1436,6 +1455,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1464,6 +1485,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = "TableViewDemo-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1472,6 +1494,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1500,6 +1524,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-tableview/RNTableView", "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", + "$(SRCROOT)/../node_modules/react-native-reanimated/ios/**", ); INFOPLIST_FILE = "TableViewDemo-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1508,6 +1533,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", diff --git a/example/package.json b/example/package.json index 801316e..2055674 100644 --- a/example/package.json +++ b/example/package.json @@ -11,8 +11,9 @@ "react": "16.8.3", "react-native": "0.59.9", "react-native-gesture-handler": "^1.3.0", + "react-native-reanimated": "^1.1.0", "react-native-tableview": "^2.5.0", - "react-navigation": "^3.11.0" + "react-navigation": "^3.11.1" }, "devDependencies": { "@babel/core": "^7.4.5", diff --git a/example/src/screens/Example4.js b/example/src/screens/Example4.js index 9faf4b1..e970e70 100644 --- a/example/src/screens/Example4.js +++ b/example/src/screens/Example4.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { View, ActivityIndicator, Text, StyleSheet } from 'react-native'; import TableView from 'react-native-tableview'; @@ -13,47 +13,47 @@ const styles = StyleSheet.create({ }, }); -class Example4 extends React.Component { - state = { - loading: true, - users: [], - }; - - async componentWillMount() { - const response = await fetch('https://randomuser.me/api/?results=5000'); - const data = await response.json(); - - this.setState({ - loading: false, - users: data.results.map(a => ({ - name: `${a.name.first} ${a.name.last}`, - id: a.registered, - })), - }); - } - - render() { - return ( - - - {this.state.loading ? 'Fetching' : 'Fetched'} 5000 users - - - {this.state.loading && } - - -
- {this.state.users.map(a => ( - {a.name} - ))} -
-
-
- ); - } -} +const Example4 = () => { + const [loading, setLoading] = useState(true); + const [users, setUsers] = useState([]); + + useEffect(() => { + const getUsers = async () => { + const response = await fetch('https://randomuser.me/api/?results=5000'); + const data = await response.json(); + + setLoading(false); + setUsers( + data.results.map(a => ({ + name: `${a.name.first} ${a.name.last}`, + id: a.registered, + })) + ); + }; + + getUsers(); + }, []); + + return ( + + + {loading ? 'Fetching' : 'Fetched'} 5000 users + + + {loading && } + + +
+ {users.map(a => ( + {a.name} + ))} +
+
+
+ ); +}; export default Example4; diff --git a/example/src/screens/Example6.js b/example/src/screens/Example6.js index ba5793b..e5de288 100644 --- a/example/src/screens/Example6.js +++ b/example/src/screens/Example6.js @@ -6,53 +6,53 @@ import TableView from 'react-native-tableview'; const { Item, Section, Consts } = TableView; -class Example6 extends React.Component { - static navigationOptions = ({ navigation }) => ({ +const Example6 = ({ navigation }) => { + return ( + + alert(JSON.stringify(event))} + onChange={event => alert(`CHANGED:${JSON.stringify(event)}`)} + > +
+ Item 1 + Item 2 + Item 3 + Item 4 +
+
+ alert(JSON.stringify(event))} + onChange={event => alert(`CHANGED:${JSON.stringify(event)}`)} + > +
+ Item 1 + Item 2 + Item 3 + Item 4 +
+
+
+ ); +}; + +Example6.navigationOptions = ({ navigation }) => { + const editing = navigation.getParam('editing'); + + return { headerRight: (