Modern web allows you to solve some of the tasks that were previously the prerogative of native mobile applications. We will create a web application (website) that will load and retain full functionality even in the absence of the Internet, and when it appears, it is automatically synchronized with the server. For a mobile device, for such an application it is enough to create a shortcut and in terms of autonomy we will get an analogue of the native application.
We will write a semblance of a todo-list, with one difference: “completed” tasks will not be deleted, but transferred to the end of the list and as the remaining tasks are solved, it will pop up. This list is convenient to use for repetitive things, such as various sports activities, entertainment, food, etc. One of my socially realized friend uses it to evenly maintain contact with a large population of his friendszone.
What you get as a result can be viewed here . Try to make some changes, close the tab, turn off the Internet and re-open the site. You will find that it opens and retains full functionality. If you log in to different devices and make changes offline, after the connection is restored, the changes are synchronized in an intuitively expected way.
You will be surprised how little code we need to implement this functionality.
In order not to clutter the text with the next webpack settings, I created a turnip with ready-made settings. Just incline it and switch to part 0: git checkout part0
. Key points to pay attention to:
npm start
- launches the hoodie-server and assembly of the application with a webpack in watch mode (reassembly when changed)public/index.html
- exactly what you thought, here we create the root div of the application and connect the bundle compiled by the webpacksrc/index.js
- entry point into the application, here we render the root component: ReactDOM.render(<App />
src/App.js
is our only component so far; here we will start writing code in the next section.Try to start the server. When the webpack says that everything is ready, at http: // localhost: 8000 / you should see a nice site header.
In order for the application to function in offline mode, we will need to store data somewhere and somehow synchronize it between devices. Pouchdb is perfect for this. But we will work with it not directly but through the Hoodie wrapper, which can authorize. Let's connect it in src/App.js
:
import Hoodie from '@hoodie/client' const hoodie = new Hoodie()
Now create a component to add a loop (a separate todo list):
import React from 'react' import TextField from 'material-ui/TextField' import RaisedButton from 'material-ui/RaisedButton' export default class AddLoop extends React.Component { constructor(props) { super(props) this.state = { title: '' } } handleTitleChange = (e) => this.setState({title: e.target.value}) handleSubmit = (e) => { e.preventDefault() this.props.store.add({ type: 'loop', title: this.state.title }) this.setState({title: ''}) } render() { return ( <form onSubmit={this.handleSubmit}> <TextField hintText="New loop" value={this.state.title} onChange={this.handleTitleChange} style={{marginRight: '10px'}} /> <RaisedButton label="Add" type="submit" primary={true} /> </form> ); } }
The bottom line here lies in the line this.props.store.add
. Where store
is hoodie.store
which we need to pass in the properties of the components when rendering it in App.js
:
render() { ... <AddLoop store={hoodie.store} />
Let's now display the documents saved in the database. In App.js
we add the loadLoops
method:
constructor(props) { super(props); this.state = { loops: [] }; this.loadLoops(); } loadLoops = () => { hoodie.store.findAll(doc => doc.type == 'loop') .then(loops => this.setState({loops})) }
We needed a constructor in which we initialize the state
and initiate the loading of documents. In hoodie.store.findAll
we pass a filter for the necessary documents and get a promise, in which we simply write the received documents to the state
.
Let's now draw them by adding to render()
:
{this.state.loops.map(loop => ( <Paper key={loop.id} zDepth={2} style={{maxWidth: 400, margin: '20px auto'}}> <h3 style={{padding: 15}}>{loop.title}</h3> </Paper> ))}
Now you should see a list of added loopes. However, when adding new ones, they will appear in the list only when the page is reloaded. Let's fix it.
All the code for this item will consist of adding a couple of lines to our App.js
:
componentDidMount() { hoodie.store.on('change', this.loadLoops); }
Now, when adding loops, they will automatically appear in the list. And no matter how the database has changed. This is important - even if changes occurred during synchronization with another device, our callback will work.
From the logic of working with the database, it becomes clear why a reaction was chosen among the abundance of browser template engines. In response to each change in DB, we will simply restart the entire state. And if I loved vue.js in place of the reactor, it would re-render the entire dom. And this is not just slow, imagine you fill out a form and at this moment another device initiates a change in the database - the form is redrawn, your changes are lost. Whereas the reaction with its virtual dom will accurately redraw the changed details and even not focus on your form.
Today we learned how to interact with browser database. In the next part, we will configure the server database and fasten the authorization. I will be glad to any of your comments / corrections / wishes. The code for this part is available here: https://github.com/imbolc/action-loop under the tag part1
.
Source: https://habr.com/ru/post/309166/
All Articles