react学習開発プロセス
52250 ワード
yarn create react-app project-name
yarn add react-app-rewired customize-cra -D
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
const {
override,
addLessLoader,
fixBabelImports, //
addDecoratorsLegacy //
} = require('customize-cra')
const modifyVars = require('./theme') //
module.exports = override(
addLessLoader({
javascriptEnabled: true,
modifyVars
}),
addDecoratorsLegacy(),
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
)
yarn add antd
yarn add less less-loader -D
yarn add babel-plugin-import -D
module.exports = {
'@primary-color': ' #1890ff', //
'@link-color': ' #1890ff', //
'@success-color': ' #52c41a', //
'@warning-color': ' #faad14', //
'@error-color': ' #f5222d', //
'@font-size - base': ' 14px', //
'@heading-color': ' rgba(0, 0, 0, 0.85)', //
'@text-color': ' rgba(0, 0, 0, 0.65)', //
'@text-color - secondary ': ' rgba(0, 0, 0, .45)', //
'@disabled-color ': ' rgba(0, 0, 0, .25)', //
'@border-radius - base': ' 4px', // /
'@border-color - base': ' #d9d9d9', //
'@box-shadow - base': ' 0 2px 8px rgba(0, 0, 0, 0.15)', //
}
yarn add @babel/plugin-proposal-decorators -D
mkdir src/components src/views src/routes src/reducers src/actions
yarn add react-router-dom
-views
-Home
-index.js
-Article
-index.js
-Edit.js
import {
Dashboard,
Login,
NotFound,
} from '../views'
export const mainRouter = [
{
pathname: '/login',
component: Login
},
{
pathname: '/404',
component: NotFound
},
]
export const adminRouter = [
{
pathname: '/admin/dashboard',
component: Dashboard
},
import React from 'react'
import { render } from 'react-dom'
import { HashRouter as Router, Route, Switch, Redirect } from 'react-router-dom'
import { mainRouter } from './routes'
import App from './App'
render(
<Router>
<Switch>
<Route path='/admin' render={routeProps => {
// TODO:
return <App {...routeProps} />
}} />
{
mainRouter.map(route => <Route
key={route.pathname}
path={route.pathname}
component={route.component}
/>)
}
<Redirect to='/admin' from='/' exact />
<Redirect to='/404' />
</Switch>
</Router>,
document.getElementById('root')
)
import React from 'react'
import { Route, Switch, Redirect } from 'react-router-dom'
import { adminRouter } from './routes'
const App = (props) => (
<div>
<div> </div>
<Switch>
{
adminRouter.map(route => (
<Route
key={route.pathname}
exact={route.exact}
path={route.pathname}
render={routerProps => (
<route.component
{...routerProps}
/>
)}
/>
))
}
<Redirect to={adminRouter[0].pathname} from='/admin' exact />
<Redirect to='/404' />
</Switch>
</div>
)
export default App
yarn add react-loadable
import { Loading } from '../components'
import Loadable from 'react-loadable'
const loadindComponent = (loader, loading = Loading) => (
Loadable({
loader,
loading
})
)
const Dashboard = loadindComponent(
() => import('./Dashboard'),
)
const Login = loadindComponent(
() => import('./Login'),
)
export {
Dashboard,
Login,
}
yarn add axios
import Axios from "axios";
const isDev = process.env.NODE_ENV === 'development'
const ajax = Axios.create({
baseURL: isDev ? 'http://rap2api.taobao.org/app/mock/244403/' : ''
})
ajax.interceptors.request.use((config) => {
config.params = Object.assign({}, config.params, {
Authorization: 'Bearer ...'
})
return config
}, err => {
console.log(err)
})
ajax.interceptors.response.use((resp) => {
return resp.data.data
}, (error) => {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
return Promise.reject(error.response.data)
// return error.response.data
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
return Promise.reject(error)
})
export const getArticles = (offset = 0, limit = 10) => {
return ajax.get('/api/v1/article', { params: { offset, limit } })
}
export const delArticles = (id) => {
return ajax.delete('/api/v1/article/' + id)
}
yarn add redux react-redux redux-thunk
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers'
export default createStore(
rootReducer,
applyMiddleware(thunk)
)
import { Provider } from 'react-redux'
import store from './store'
<Provider store={store}>
...
</Provider>
export default {
MARK_NOTIFICATION_AS_READ_BY_ID: 'MARK_NOTIFICATION_AS_READ_BY_ID',
...
GET_NOTIFICATIONS: 'GET_NOTIFICATIONS',
};
import actionType from './actionTypes'
import { getNotifications } from '../requests'
export const markNotificationAsReadByid = (id) => {
return dispatch => {
dispatch(startNotification())
setTimeout(() => {
dispatch({
type: actionType.MARK_NOTIFICATION_AS_READ_BY_ID,
payload: { id }
})
dispatch(endNotification())
}, 2000)
}
}
...
export const endNotification = () => {
return {
type: actionType.END_NOTIFICATION_LODING,
}
}
export const notifications = () => {
return dispatch => {
dispatch(startNotification())
getNotifications().then((resp) => {
dispatch({
type: actionType.GET_NOTIFICATIONS,
payload: {
list: resp.list
}
})
}).finally(() => {
dispatch(endNotification())
})
}
}
import { combineReducers } from 'redux'
import notifications from './notifications'
export default combineReducers({
notifications
})
import actionTypes from '../actions/actionTypes'
const initState = {
isLoading: true,
list: []
}
export default (state = initState, action) => {
switch (action.type) {
case actionTypes.START_NOTIFICATION_LODING:
return {
...state,
isLoading: true
}
case actionTypes.GET_NOTIFICATIONS:
return {
...state,
list: action.payload.list,
}
case actionTypes.MARK_NOTIFICATION_AS_READ_BY_ID:
return {
...state,
list: state.list.map(item => {
if (item.id === action.payload.id)
item.hasRead = true
return item
})
}
...
case actionTypes.END_NOTIFICATION_LODING:
return {
...state,
isLoading: false
}
default:
return state
}
}
import { connect } from 'react-redux'
import { markNotificationAsReadByid, markAllNotificationsAsRead } from '../../actions/notifications'
const mapStateToProps = state => {
const {
list, isLoading
} = state.notifications
return {
list, isLoading
}
}
function Notification(props) {
return (
<Spin spinning={props.isLoading} >
<Card
title=' '
bordered={false}
extra={
<Button
disabled={props.list.every(item => item.hasRead === true)}
onClick={() => {
props.markAllNotificationsAsRead()
}}
> </Button>
}
>
<List
itemLayout="horizontal"
dataSource={props.list}
renderItem={item => (
<List.Item
extra={
item.hasRead ? null : <Button
onClick={() => {
props.markNotificationAsReadByid(item.id)
}}
> </Button>
}
>
<List.Item.Meta
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
title={<Badge dot={!item.hasRead} >{item.title}</Badge>}
description={item.desc}
/>
</List.Item>
)}
/>
</Card>
</Spin>
)
}
export default connect(mapStateToProps, { markNotificationAsReadByid, markAllNotificationsAsRead })(Notification)