Skip to content

Commit

Permalink
add
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankFang committed Jun 15, 2019
1 parent da0de97 commit 2a5df0b
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 124 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,4 +1,5 @@
/.idea
/dist
# Logs
logs
*.log
Expand Down
13 changes: 12 additions & 1 deletion package.json
@@ -1,5 +1,5 @@
{
"name": "PromiseComponent",
"name": "promise-component",
"version": "1.0.0",
"description": "My webpack project",
"main": "index.js",
Expand All @@ -20,13 +20,24 @@
},
"homepage": "https://github.com/FrankFang/PromiseComponent#readme",
"devDependencies": {
"@types/react": "^16.8.20",
"@types/react-dom": "^16.8.4",
"@webpack-cli/init": "^0.2.2",
"awesome-typescript-loader": "^5.2.1",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"html-webpack-plugin": "^3.2.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"ts-loader": "^6.0.2",
"typescript": "^3.5.2",
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4",
"webpack-dev-server": "^3.7.1"
},
"peerDependencies": {
"@types/react": ">=16.8.0",
"@types/react-dom": ">=16.8.0",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
}
8 changes: 8 additions & 0 deletions src/demo.css
@@ -0,0 +1,8 @@
.loading {
display: inline-block;
width: 1em;
height: 1em;
border-radius: 50%;
box-sizing: border-box;
border: 1px solid black;
}
1 change: 0 additions & 1 deletion src/demo.ts

This file was deleted.

61 changes: 61 additions & 0 deletions src/demo.tsx
@@ -0,0 +1,61 @@
import React from 'react';
import ReactDOM from 'react-dom';
import promiseComponent from './index';
import './demo.css';

const root = document.createElement('div');
document.body.append(root);

type Resource = Array<{ id: number, name: string }>

const ComponentOne = promiseComponent<{}, Resource | Error>({
promiser: () => ajax(),
render({props, status, result, run}) {
console.log('result');
console.log(result);
switch (status) {
case 'initial':
return (<>
<button onClick={run}>搜索</button>
</>);
case 'pending':
return (<>
<button disabled>搜索</button>
<span className="loading"/>
</>);
case 'fulfilled':
return (<>
<button onClick={run}>搜索</button>
<div>
成功 {JSON.stringify(result)}
</div>
</>);
case 'rejected':
return (<>
<button onClick={run}>搜索</button>
<div>
失败 {(result as Error).message}
</div>
</>);
}
}
});

ReactDOM.render(<div>
<ComponentOne/>
</div>, root);

function ajax() {
return new Promise<Resource | Error>((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve([
{id: 1, name: 'Frank'},
{id: 2, name: 'Jack'}
]);
} else {
reject(new Error('network broken'));
}
}, 1500);
});
}
1 change: 0 additions & 1 deletion src/index.ts

This file was deleted.

36 changes: 36 additions & 0 deletions src/index.tsx
@@ -0,0 +1,36 @@
import React, {ReactNode, useState} from 'react';


interface Props<P, T> {
promiser: (props: P) => Promise<T>;
render: (options: PromiseComponentRender<P, T>) => ReactNode;
}

export interface PromiseComponentRender<P, T> {
props: P;
status: PromiseStatuses;
result?: T;
run: () => void;
}

type PromiseStatuses = 'initial' | 'pending' | 'fulfilled' | 'rejected' ;

function promiseComponent<P, T>({promiser, render}: Props<P, T>) {
return function C(props: P) {
const [state, setState] = useState<Pick<PromiseComponentRender<P, T>, 'status' | 'result'>>({
status: 'initial'
});
const run = () => {
setState({status: 'pending'});
promiser(props).then((result) => {
setState({status: 'fulfilled', result});
}, (result) => {
setState({status: 'rejected', result});
});
};
return (
<>{render({props, run, ...state})}</>
);
};
};
export default promiseComponent;
8 changes: 7 additions & 1 deletion tsconfig.json
Expand Up @@ -4,6 +4,12 @@
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"allowJs": true
"allowJs": true,
"jsx": "react"
},
"awesomeTypescriptLoaderOptions": {
"reportFiles": [
"./src/**/*"
]
}
}
132 changes: 57 additions & 75 deletions webpack.config.js
@@ -1,77 +1,59 @@
const path = require('path');
const webpack = require('webpack');

/*
* SplitChunksPlugin is enabled by default and replaced
* deprecated CommonsChunkPlugin. It automatically identifies modules which
* should be splitted of chunk by heuristics using module duplication count and
* module category (i. e. node_modules). And splits the chunks…
*
* It is safe to remove "splitChunks" from the generated configuration
* and was added as an educational example.
*
* https://webpack.js.org/plugins/split-chunks-plugin/
*
*/

const HtmlWebpackPlugin = require('html-webpack-plugin');

/*
* We've enabled HtmlWebpackPlugin for you! This generates a html
* page for you when you compile webpack, which will make you start
* developing and prototyping faster.
*
* https://github.com/jantimon/html-webpack-plugin
*
*/
const path = require('path')
const webpack = require('webpack')
const {CheckerPlugin} = require('awesome-typescript-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
mode: 'development',

entry: {
index: './src/index.ts',
demo: './src/demo.ts'
},

output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
},

plugins: [new webpack.ProgressPlugin(), new HtmlWebpackPlugin()],

module: {
rules: [
{
test: /.(ts|tsx)?$/,
loader: 'ts-loader',
include: [path.resolve(__dirname, 'src')],
exclude: [/node_modules/]
}
]
},

optimization: {
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},

chunks: 'async',
minChunks: 1,
minSize: 30000,
name: true
}
},

devServer: {
open: true
},

resolve: {
extensions: ['.tsx', '.ts', '.js']
}
};
mode: 'development',

entry: {
index: './src/index.tsx',
demo: './src/demo.tsx'
},

output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
},

plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin(),
new CheckerPlugin()
],

module: {
rules: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
include: [path.resolve(__dirname, 'src')],
exclude: [/node_modules/]
}
]
},

optimization: {
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},

chunks: 'async',
minChunks: 1,
minSize: 30000,
name: true
}
},

devServer: {
open: false
},

resolve: {
extensions: ['.tsx', '.ts', '.js']
}
}

0 comments on commit 2a5df0b

Please sign in to comment.