Skip to content

Commit 7c3a242

Browse files
committed
feat: initial version
0 parents  commit 7c3a242

10 files changed

Lines changed: 16745 additions & 0 deletions

File tree

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
这是一个演示 React hooks 的 demo. 也用到 [LeanCloud](https://leancloud.cn) 来做数据存储。
2+
3+
相关的代码主要在 [`src/App.js`](src/App.js)。可以在本地用 `npm start` 来运行项目。
4+
5+
注意这个项目使用的是 LeanCloud 的一个开发版应用,在测试的人多时可能会因为超出请求数限制而出错。如果要基于它做进一步开发,建议尽快替换自己的 AppId 和 AppKey。

package-lock.json

Lines changed: 16509 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "leancloud-react-hook-tutorial",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"leancloud-storage": "^3.12.0",
7+
"react": "^16.8.6",
8+
"react-dom": "^16.8.6",
9+
"react-scripts": "2.1.8"
10+
},
11+
"scripts": {
12+
"start": "react-scripts start",
13+
"build": "react-scripts build",
14+
"test": "react-scripts test",
15+
"eject": "react-scripts eject"
16+
},
17+
"eslintConfig": {
18+
"extends": "react-app"
19+
},
20+
"browserslist": [
21+
">0.2%",
22+
"not dead",
23+
"not ie <= 11",
24+
"not op_mini all"
25+
]
26+
}

public/favicon.ico

3.78 KB
Binary file not shown.

public/index.html

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1, shrink-to-fit=no"
9+
/>
10+
<meta name="theme-color" content="#000000" />
11+
<!--
12+
manifest.json provides metadata used when your web app is installed on a
13+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
14+
-->
15+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
16+
<!--
17+
Notice the use of %PUBLIC_URL% in the tags above.
18+
It will be replaced with the URL of the `public` folder during the build.
19+
Only files inside the `public` folder can be referenced from the HTML.
20+
21+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
22+
work correctly both with client-side routing and a non-root public URL.
23+
Learn how to configure a non-root public URL by running `npm run build`.
24+
-->
25+
<title>React App</title>
26+
</head>
27+
<body>
28+
<noscript>You need to enable JavaScript to run this app.</noscript>
29+
<div id="root"></div>
30+
<!--
31+
This HTML file is a template.
32+
If you open it directly in the browser, you will see an empty page.
33+
34+
You can add webfonts, meta tags, or analytics to this file.
35+
The build step will place the bundled scripts into the <body> tag.
36+
37+
To begin the development, run `npm start` or `yarn start`.
38+
To create a production bundle, use `npm run build` or `yarn build`.
39+
-->
40+
</body>
41+
</html>

public/manifest.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
}
10+
],
11+
"start_url": ".",
12+
"display": "standalone",
13+
"theme_color": "#000000",
14+
"background_color": "#ffffff"
15+
}

src/App.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// -*-RJSX-*-
2+
3+
import React, { useState } from 'react';
4+
import LC from 'leancloud-storage';
5+
import AppStyles from './App.module.css';
6+
7+
LC.init('B09iIN0UKf2qQIjqKz5WiRnv-gzGzoHsz', 'Xes23aMR9VUqzpmEvch8YV4A');
8+
9+
function saveTodo(content) {
10+
const Todo = LC.Object.extend('Todo');
11+
const todo = new Todo();
12+
todo.set('content', content);
13+
todo.set('finished', false);
14+
return todo.save();
15+
}
16+
17+
function loadTodos() {
18+
const query = new LC.Query('Todo');
19+
query.equalTo('finished', false);
20+
query.limit(20);
21+
query.descending('createdAt');
22+
return query.find();
23+
}
24+
25+
function App() {
26+
const [inputValue, setInputValue] = useState('');
27+
const [todos, setTodos] = useState(undefined);
28+
const [error, setError] = useState('');
29+
const addTodo = () => {
30+
saveTodo(inputValue).then(todo => {
31+
setInputValue('');
32+
setTodos(prev => [todo].concat(prev));
33+
}).catch(setError);
34+
};
35+
36+
if (todos === undefined) {
37+
loadTodos().then(setTodos).catch(setError);
38+
}
39+
40+
const toggle = item => {
41+
item.set('finished', !item.get('finished'));
42+
item.save().then(() => setTodos(prev => prev.slice(0))).catch(setError);
43+
};
44+
45+
return (
46+
<div className={AppStyles.app}>
47+
<div className={AppStyles.error}>{error.toString()}</div>
48+
<div className={AppStyles.add}>
49+
<input placeholder="What to do next?" value={inputValue}
50+
onChange={e => setInputValue(e.target.value)}
51+
onKeyUp={e => { if (e.keyCode === 13) addTodo(); } } />
52+
<input type="button" value="↩" />
53+
</div>
54+
<ul>
55+
{todos && todos.map(item =>
56+
<li key={item.getObjectId()} onClick={() => toggle(item)}
57+
data-finished={item.get('finished')}>
58+
{item.get('content')}
59+
</li> )}
60+
</ul>
61+
</div>
62+
);
63+
}
64+
65+
export default App;

src/App.module.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
* {
2+
padding: 0;
3+
margin: 0;
4+
box-sizing: border-box;
5+
}
6+
7+
html {
8+
font-size: 10px;
9+
font-family: -apple-system, 'BlinkMacSystemFont', 'Helvetica Neue', 'Arial', sans-serif;
10+
}
11+
12+
.app {
13+
max-width: 640px;
14+
display: flex;
15+
flex-direction: column;
16+
font-size: 4rem;
17+
margin: 0 auto;
18+
}
19+
20+
.add {
21+
width: 100%;
22+
display: flex;
23+
border-bottom: solid black 1px;
24+
}
25+
26+
.add input {
27+
background-color: transparent;
28+
border: 0;
29+
font-size: 4rem;
30+
flex-grow: 1;
31+
}
32+
33+
.add input[type=button] {
34+
width: 5rem;
35+
height: 5rem;
36+
flex-grow: 0;
37+
cursor: pointer;
38+
}
39+
40+
.error {
41+
color: red;
42+
}
43+
44+
.app ul {
45+
list-style: none;
46+
margin-top: 2rem;
47+
}
48+
49+
.app li {
50+
cursor: pointer;
51+
}
52+
53+
.app li[data-finished=true] {
54+
text-decoration: line-through;
55+
color: gray;
56+
}

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import App from './App';
4+
5+
ReactDOM.render(<App />, document.getElementById('root'));

0 commit comments

Comments
 (0)