diff --git a/doc/7/getting-started/.react-native/App.js b/doc/7/getting-started/.react-native/App.js
index c5e9c20a9..d388bff5f 100644
--- a/doc/7/getting-started/.react-native/App.js
+++ b/doc/7/getting-started/.react-native/App.js
@@ -1,34 +1,39 @@
+/* snippet:start:1 */
import React from 'react';
import Login from './screens/Login/Login';
import ChatClient from './screens/Chat/ChatClient';
+/* snippet:end */
- class App extends React.Component {
+/* snippet:start:2 */
+export default class App extends React.Component {
constructor(props) {
- super(props);
- this.handleSubmitName = this.onSubmitName.bind(this);
- this.state = {
+ super(props);
+ this.handleSubmitName = this.onSubmitName.bind(this);
+ this.state = {
hasName: false
};
}
-
- onSubmitName(e) {
+ /* snippet:end */
+ /* snippet:start:3 */
+ onSubmitName(e) {
const name = e.nativeEvent.text;
this.setState({
name,
hasName: true
});
}
-
+ /* snippet:end */
+ /* snippet:start:4 */
render() {
if (this.state.hasName) {
return (
-
+
);
} else {
return (
-
+
);
}
}
}
-export default App;
\ No newline at end of file
+/* snippet:end */
\ No newline at end of file
diff --git a/doc/7/getting-started/.react-native/screens/Chat/ChatClient.js b/doc/7/getting-started/.react-native/screens/Chat/ChatClient.js
index 58e667a8a..8ae420b2a 100644
--- a/doc/7/getting-started/.react-native/screens/Chat/ChatClient.js
+++ b/doc/7/getting-started/.react-native/screens/Chat/ChatClient.js
@@ -1,7 +1,10 @@
+/* snippet:start:1 */
import React from 'react';
import ChatView from './ChatView';
import kuzzle from '../../services/kuzzle';
+/* snippet:end */
+/* snippet:start:2 */
class ChatClient extends React.Component {
constructor(props) {
super(props);
@@ -28,6 +31,9 @@ class ChatClient extends React.Component {
await kuzzle.collection.create("chat", "messages");
}
}
+ /* snippet:end */
+
+ /* snippet:start:4 */
displayDate(previousDate, currentDate) {
if (previousDate === null) {// Message is the first of the array so need to display the date
return true;
@@ -41,6 +47,9 @@ class ChatClient extends React.Component {
// Previous message and current has same dates so doesn't need to display the date
return false;
}
+ /* snippet:end */
+
+ /* snippet:start:5 */
getMessage(msg, displayDate) {
const message = {
// The unique id of the document containing the message
@@ -58,6 +67,9 @@ class ChatClient extends React.Component {
// and only the hours on each messages
return message;
}
+ /* snippet:end */
+
+ /* snippet:start:6 */
async fetchMessages() {
// Call the search method of the document controller
const results = await this.kuzzle.document.search(
@@ -79,7 +91,9 @@ class ChatClient extends React.Component {
})
});
}
+ /* snippet:end */
+ /* snippet:start:7 */
async subscribeMessages() {
// Call the subscribe method of the realtime controller and receive the roomId
const roomId = await this.kuzzle.realtime.subscribe(
@@ -87,7 +101,7 @@ class ChatClient extends React.Component {
"messages", // Id of the collection
{}, // Filter
// Callback to receive notifications
- notification => {
+ async notification => {
// Check if the notification interest us (only document creation)
if (notification.type !== "document") return;
if (notification.action !== "create") return;
@@ -99,7 +113,7 @@ class ChatClient extends React.Component {
displayDate = this.displayDate(this.state.messages[length - 1].date, notification.result._source._kuzzle_info.createdAt);
}
// Add the new message to our array
- this.setState({
+ await this.setState({
messages: [...this.state.messages.slice(), this.getMessage(notification.result, displayDate)]
});
}
@@ -107,7 +121,9 @@ class ChatClient extends React.Component {
// Save the id of our subscription (we could need it to unsubscribe)
this.setState({ roomId: roomId });
}
+ /* snippet:end */
+ /* snippet:start:8 */
async onSendMessage(message) {
await kuzzle.document.create(
"chat",
@@ -119,7 +135,9 @@ class ChatClient extends React.Component {
}
);
}
+ /* snippet:end */
+ /* snippet:start:9 */
render() {
const messages = this.state.messages;
return (
@@ -128,3 +146,4 @@ class ChatClient extends React.Component {
}
}
export default ChatClient;
+/* snippet:end */
diff --git a/doc/7/getting-started/.react-native/screens/Chat/ChatView.js b/doc/7/getting-started/.react-native/screens/Chat/ChatView.js
index 628e86fd2..becc142f0 100644
--- a/doc/7/getting-started/.react-native/screens/Chat/ChatView.js
+++ b/doc/7/getting-started/.react-native/screens/Chat/ChatView.js
@@ -1,3 +1,4 @@
+/* snippet:start:1 */
import React from 'react';
import {
StyleSheet,
@@ -8,22 +9,25 @@ import {
SafeAreaView,
KeyboardAvoidingView
} from 'react-native';
-
+/* snippet:end */
+/* snippet:start:2 */
class ChatView extends React.Component {
constructor(props) {
super(props);
this.handleSendMessage = this.onSendMessage.bind(this);
}
-
onSendMessage = e => {
this.props.onSendMessage(e.nativeEvent.text);
this.refs.input.clear();
}
+ /* snippet:end */
+ /* snippet:start:4 */
getDate(timestamp) {
const date = new Date(timestamp);
return date.toTimeString().split('GMT')[0];
}
-
+ /* snippet:end */
+ /* snippet:start:5 */
render() {
return (
@@ -32,14 +36,14 @@ class ChatView extends React.Component {
style={styles.list}
data={this.props.messages}
ref={ref => this.flatList = ref}
- onContentSizeChange={() => this.flatList.scrollToEnd({animated: true})}
+ onContentSizeChange={() => this.flatList.scrollToEnd({ animated: true })}
renderItem={({ item }) =>
{
- item.displayDate ?
- {new Date(item.date).toDateString()} :
- null
+ item.displayDate ?
+ {new Date(item.date).toDateString()} :
+ null
}
item.id}
/>
+ {/* snippet:end */}
+ {/* snippet:start:6 */}
+ {/* snippet:end */}
+ {/* snippet:start:7 */}
);
}
}
+/* snippet:end */
+/* snippet:start:8 */
const offset = 24;
const styles = StyleSheet.create({
name: {
@@ -121,4 +131,5 @@ const styles = StyleSheet.create({
paddingHorizontal: offset,
}
});
-export default ChatView;
\ No newline at end of file
+export default ChatView;
+/* snippet:end */
diff --git a/doc/7/getting-started/.react-native/screens/Login/Login.js b/doc/7/getting-started/.react-native/screens/Login/Login.js
index 2883c1320..f51ec5741 100644
--- a/doc/7/getting-started/.react-native/screens/Login/Login.js
+++ b/doc/7/getting-started/.react-native/screens/Login/Login.js
@@ -1,6 +1,8 @@
+/* snippet:start:1 */
import React from 'react';
import { StyleSheet, Text, TextInput, KeyboardAvoidingView } from 'react-native';
-
+/* snippet:end */
+/* snippet:start:2 */
export default class Login extends React.Component {
render() {
return (
@@ -21,7 +23,8 @@ export default class Login extends React.Component {
);
}
}
-
+/* snippet:end */
+/* snippet:start:3 */
const styles = StyleSheet.create({
container: {
flex: 1,
@@ -33,4 +36,5 @@ const styles = StyleSheet.create({
alignSelf: 'stretch',
textAlign: 'center'
}
-});
\ No newline at end of file
+});
+/* snippet:end */
diff --git a/doc/7/getting-started/react-native/index.md b/doc/7/getting-started/react-native/index.md
new file mode 100644
index 000000000..09d7e833f
--- /dev/null
+++ b/doc/7/getting-started/react-native/index.md
@@ -0,0 +1,189 @@
+---
+type: page
+code: false
+title: React Native
+description: Getting started with Kuzzle and React Native using Expo
+order: 400
+---
+
+
+# Getting Started with Kuzzle and React Native
+
+This section deals with **Kuzzle** (+ [**Javascript SDK**](/sdk/js/7/)) and **React Native**. We will create **documents** in Kuzzle and subscribe to [document notifications](/sdk/js/7/essentials/realtime-notifications/#document-messages) to develop a realtime chat.
+
+
+## Requirements
+
+- **Node.js** >= 12.0.0 ([install here](https://nodejs.org/en/download/))
+- **Running Kuzzle Stack** ([instructions here](/core/2/guides/getting-started/running-kuzzle/))
+- **Expo CLI** ([install here](https://docs.expo.io/versions/v36.0.0/get-started/installation/))
+
+"[Expo](https://docs.expo.io/versions/latest/) is a framework and a platform for universal React applications. It is a set of tools and services built around React Native and native platforms that help you develop, build, deploy, and quickly iterate on iOS, Android, and web apps from the same JavaScript/TypeScript codebase."
+
+## Prepare your environment
+
+Create your React Native app with Expo CLI.
+```bash
+expo init getting-started-kuzzle
+```
+You can use yarn to install dependencies if you want.
+Then choose a blank project, type 'Kuzzle' and type y.
+
+Install Kuzzle's Javascript SDK:
+```bash
+cd getting-started-kuzzle
+npm install kuzzle-sdk
+```
+
+Now, you can run your app and access it by different ways:
+
+ - To test it on your smartphone, you'll need to download the
+ expo application and scan the displayed qrCode after running this command:
+ ```bash
+ expo start
+ ```
+ - To test it in your browser, you can run the following command:
+ ```bash
+ expo start --web
+ ```
+
+## Get the username
+First of all, we need to know the user's name.
+Let's start creating the following file _screens/Login/Login.js_ and add some imports.
+
+<<< ./snippets/Login.js.snippet:1[js]
+
+Then we must export our `Login` class with the render function:
+
+<<< ./snippets/Login.js.snippet:2[js]
+
+As you can see, this component has no state. It'll send the typed username
+to his parent component by a `onSubmitName` method passed as props.
+
+To finish, we can add some style properties to let our login page looks prettier.
+
+<<< ./snippets/Login.js.snippet:3[js]
+
+This parent component of _Login.js_ will be _App.js_ so let's work on it.
+
+You can delete all the code from the _App.js_ file, we will rewrite it.
+
+First, add the following imports:
+
+<<< ./snippets/App.js.snippet:1[js]
+
+Then we need to do three changes:
+ - First, we must export our *App* class:
+<<< ./snippets/App.js.snippet:2[js]
+ - Then we need to create our `onSubmitName` function:
+<<< ./snippets/App.js.snippet:3[js]
+ - Finally we will create our render function:
+<<< ./snippets/App.js.snippet:4[js]
+
+You can see that we will have to create a new component, `ChatClient`.
+That new component will contain the link to our Kuzzle backend so we need first declare our Kuzzle service.
+
+
+## Instantiating Kuzzle SDK and Adding logical part
+
+We have to connect the server so our client can interact with it.
+
+To do this, we have to create a _/services/kuzzle.js_ file to put our Kuzzle instance declaration:
+
+<<< ./snippets/kuzzle.js.snippet[js]
+
+Note that if you are running your application on your smartphone, you must be connected on the same network and you'll need to change the `localhost` in the previous snippet by your computer ip address.
+
+We can now create a _screens/Chat/ChatClient.js_ file to use our kuzzle service.
+
+Like in our previous components, we'll first need to add our imports:
+
+<<< ./snippets/ChatClient.js.snippet:1[js]
+
+Then we will create our state that will contains our messages and call the function that will initialize our kuzzle by [establish the connection](/sdk/js/7/core-classes/kuzzle/connect/) to kuzzle and create, if they don't [exist](sdk/js/7/controllers/index/exists/), the [index](sdk/js/6/controllers/index/create/) and [collection](sdk/js/7/controllers/collection/create/) of our chat.
+
+<<< ./snippets/ChatClient.js.snippet:2[js]
+
+You can see that we are calling two functions at the end:
+`fetchMessages()` and `subscribeMessages()`, let's write them.
+
+Create the following function to fetch the messages:
+
+<<< ./snippets/ChatClient.js.snippet:6[js]
+
+The function `fetchMessage()` will [search](/sdk/js/7/controllers/document/search/) for the first hundred newest messages and store them in our state, before subscribing to changes in the `messages` collection.
+
+Then, create the `subscribeMessages()` function.
+It will call the Kuzzle's realtime controller to allow us to [receive notifications](/sdk/js/7/controllers/realtime/subscribe/) on message creations:
+
+<<< ./snippets/ChatClient.js.snippet:7[js]
+
+You can see in the two function we just wrote a call to a `getMessage()` function when we are adding a new message to the state. This function will format our Kuzzle's notification/response.
+
+<<< ./snippets/ChatClient.js.snippet:5[js]
+
+Note: The first part of this function is optional and can be replaced by a set of the `display` variable to false.
+
+If you decided to add the optional part, you'll need to implement the `displayDate()` function:
+
+<<< ./snippets/ChatClient.js.snippet:4[js]
+
+In the constructor of this component, we set a `handleSendMessage` property to a bound `onSendMessage` function. Let's implement that function:
+
+<<< ./snippets/ChatClient.js.snippet:8[js]
+
+This simple method will [create](/sdk/js/7/controllers/document/create/) a new message document in Kuzzle.
+
+As you can see we don't push the new message in our array on message creation.
+
+Indeed, we will receive notifications from Kuzzle each time we modify our message collection (even if it is a message creation on our part) that we will use to add the messages in our array.
+
+Since this component is used to do the connection to Kuzzle, it will render another one that will display the messages _screens/Chat/ChatView.js_.
+To finish, we just need to add the `render()` function:
+
+<<< ./snippets/ChatClient.js.snippet:9[js]
+
+As you can see, we are passing as props the fetched messages, the client username and the `handleSendMessage` function.
+
+## Display and Send messages
+
+In this part we'll work on another component, so we need to create the _screens/Chat/ChatView.js_ file.
+
+Then, just add the following imports:
+
+<<< ./snippets/ChatView.js.snippet:1[js]
+
+Now we need to create ou `ChatView` class and bind a `handleSendMessage` property to an `onSendMessage` function that will call the props parent function.
+
+<<< ./snippets/ChatView.js.snippet:2[js]
+
+There is no logic in this component so let's work on the render function:
+
+<<< ./snippets/ChatView.js.snippet:5[js]
+
+In the previous snippet, you can see that we are using a `Flatlist` to display the messages passed as props from the `ChatClient` component.
+The first view part in the `Flatlist` to the previous optional part. It is used to display the date only once for each message sent at the same date.
+
+Then just add the `TextInput` part with a call to our `handleSendMessage` property:
+
+<<< ./snippets/ChatView.js.snippet:6[js]
+
+And don't forget to close the opened tags:
+
+<<< ./snippets/ChatView.js.snippet:7[js]
+
+To finish, just add the style part to make it beautiful:
+
+<<< ./snippets/ChatView.js.snippet:8[js]
+
+You can now add new messages to Kuzzle and receive the creation notification to update your state and display the new messages.
+
+## Where do we go from here?
+
+Now that you're more familiar with Kuzzle, dive even deeper to learn how to leverage its full capabilities:
+
+- discover what this SDK has to offer by browsing other sections of this documentation
+- learn more about Kuzzle [realtime engine](/core/2/guides/essentials/real-time/)
+- follow our guide to learn how to [manage users, and how to set up fine-grained access control](/core/2/guides/essentials/security/)
+- lean how to use Kuzzle [Admin Console](/core/2/guides/essentials/admin-console/) to manage your users and data
+- learn how to perform a [basic authentication](/sdk/js/7/controllers/auth/login)
diff --git a/doc/7/getting-started/react-native/snippets/App.js.snippet b/doc/7/getting-started/react-native/snippets/App.js.snippet
new file mode 120000
index 000000000..a08efb8f9
--- /dev/null
+++ b/doc/7/getting-started/react-native/snippets/App.js.snippet
@@ -0,0 +1 @@
+../../.react-native/App.js
\ No newline at end of file
diff --git a/doc/7/getting-started/react-native/snippets/ChatClient.js.snippet b/doc/7/getting-started/react-native/snippets/ChatClient.js.snippet
new file mode 120000
index 000000000..3773d18d9
--- /dev/null
+++ b/doc/7/getting-started/react-native/snippets/ChatClient.js.snippet
@@ -0,0 +1 @@
+../../.react-native/screens/Chat/ChatClient.js
\ No newline at end of file
diff --git a/doc/7/getting-started/react-native/snippets/ChatView.js.snippet b/doc/7/getting-started/react-native/snippets/ChatView.js.snippet
new file mode 120000
index 000000000..de47a09e1
--- /dev/null
+++ b/doc/7/getting-started/react-native/snippets/ChatView.js.snippet
@@ -0,0 +1 @@
+../../.react-native/screens/Chat/ChatView.js
\ No newline at end of file
diff --git a/doc/7/getting-started/react-native/snippets/Login.js.snippet b/doc/7/getting-started/react-native/snippets/Login.js.snippet
new file mode 120000
index 000000000..c84d1cfad
--- /dev/null
+++ b/doc/7/getting-started/react-native/snippets/Login.js.snippet
@@ -0,0 +1 @@
+../../.react-native/screens/Login/Login.js
\ No newline at end of file
diff --git a/doc/7/getting-started/react-native/snippets/kuzzle.js.snippet b/doc/7/getting-started/react-native/snippets/kuzzle.js.snippet
new file mode 120000
index 000000000..db6b05758
--- /dev/null
+++ b/doc/7/getting-started/react-native/snippets/kuzzle.js.snippet
@@ -0,0 +1 @@
+../../.react-native/services/kuzzle.js
\ No newline at end of file