Open rogerxu opened 7 years ago
Getting Started with React – An Overview and Walkthrough – Tania Rascia A Complete Beginner's Guide to React - DEV Community 👩💻👨💻
Pros
var HelloMessage = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
getDefaultProps: function () {
return {
title : 'Hello World'
};
},
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
{}
for JavaScript expressionrender
factory function => rendererthis.props
=> propertiesthis.state
=> data model
this.getInitialState()
- get initial datathis.setState({key: value})
- update dataDetails
this.props.children
=> all children nodes - undefined
, object
or array
React.Children
to handle this.props.children
propTypes
for property metadatagetDefaultProps
factory function for default property valuesthis.refs.<refName>
- the DOM object of a ref="refName"
nodeonChange
to read event.target.value
for user input valueIt allows you to model your application in terms of Actions, Stores, and Views. It also has a part known as Dispatcher to manage actions and allow you to model dependencies between different calls.
https://survivejs.com/eccd841152209cbde7cbe79d4e72ec2e.png
https://survivejs.com/1e3f32400990086df1776cd97a7ea6ce.png
http://7tszky.com1.z0.glb.clouddn.com/FonZpI0A0bUAcv1jwAhJdALdqDOj
dispatcher.register(callback)
dispatcher.dispatch(action)
dispatcher.waitFor(promiseIndexes, callback)
store.addChangeListener(listener)
store.removeChangeListener(listener)
Actions.create(text)
dispatcher.dispatch()
Actions.destroy(id)
dispatcher.dispatch()
http://7tszky.com1.z0.glb.clouddn.com/FulidOFq7yfm-fyPHy9qm50JDu-K
In Alt, you'll deal with actions and stores. The dispatcher is hidden, but you will still have access to it if needed. Compared to other implementations, Alt hides a lot of boilerplate.
app/libs/alt.js
Normally state management solutions provide two parts you can use to connect them with a React application. These are a Provider
component and a connect
higher order function (function returning function generating a component). The Provider
sets up a React context.
Provider
app/components/Provider/index.js
app/components/Provider/Provider.prod.jsx
app/components/Provider/Provider.dev.jsx
app/components/Provider/setup.js
app/index.jsx
import Provider from './components/Provider';
ReactDOM.render(
<Provider><App /></Provider>,
document.getElementById('app')
);
connect
connect
allows us to attach specific data and actions to components.
app/libs/connect.jsx
(stateFunc, actions, target = App) => Connect
app/components/App.jsx
export default connect(stateFunc)(App);
app/stores/NoteStore.js
export default class NoteStore {
constructor() {
this.notes = [];
}
}
app/components/App.jsx
Now App component can consume data from store instead of state.
class App extends React.Component {
render() {
const {notes} = this.props;
}
}
export default connect(({ notes }) => ({
notes
}))(App);
app/actions/NoteAction.js
export default alt.generateActions('create', 'update', 'delete');
app/stores/NoteStore.js
export default class NoteStore {
constructor() {
this.bindActions(NoteActions);
this.notes = [];
}
create(note) {
this.setState({
notes: this.notes.concat(note)
});
}
}
app/components/App.jsx
class App extends React.Component {
addNote = () => {
this.props.NoteActions.create({});
}
}
浅谈 React、Flux 与 Redux - 腾讯Web前端 IMWeb 团队社区 | blog | 团队博客 flux vs redux vs mobx
https://cdn-images-1.medium.com/max/1000/1*kDO26wU8yMn0Xq7crphztA.png
store.dispatch(action)
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
actions/sample-actions.js
import { createAction } from 'redux-actions';
export const MAKE_BARK = 'MAKE_BARK';
export const makeBark = createAction(MAKE_BARK, () => true);
Use bound action creator to automatically dispatch actions
const boundAddTodo = (text) => dispatch(addTodo(text));
boundAddTodo(text);
bindActionCreators
bindActionCreators()
const reducer = (state = initialState, action) => {
// ...
return new_state;
};
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
todos,
filter,
);
Put all top-level reducers into a separate file ../reducers/index.js
, export each reducer function, and use import * as reducers
to get the as an object with their names as the keys.
import { combineReducers } from 'redux';
import * as reducers from './reducers';
const rootReducer = combineReducers(reducers);
reducers/sample-reducer.js
import Immutable from 'immutable';
const initialState = Immutable.Map({
hasBarked: false,
});
const sampleReducer = (state = initialState, action) => {
switch (action.type) {
case SAMPLE:
return state.set('hasBarked', action.payload);
default:
return state;
}
};
export default sampleReducer;
import { createStore } from 'redux';
import { combineReducers } from 'redux-immutable';
There is only one single store in a Redux application.
import { createStore } from 'redux';
import reducer from './reducers';
const store = createStore(reducer);
const state = store.getState();
store.dispatch(action);
http://7tszky.com1.z0.glb.clouddn.com/FqwrgoH93cl8a5f3oFc0XZL7waBQ
store = dispatcher + reducer
http://zhenhua-lee.github.io/img/react/redux.png
component.onClick()
action = createAction(type, payload)
store.dispatch(action)
newState = reducer(previousState, action)
listener.invoke()
component.render()
newState = store.getState()
component.setProps('value', newState.value)
Redux 入门教程(二):中间件与异步操作 - 阮一峰的网络日志
Middlewares are used to redefine store.dispatch
method to make it accept action other than an object. For example, function or Promise.
applyMiddleware
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import rootReducer from './reducers';
const logger = createLogger();
const store = createStore(
rootReducer,
initialState,
applyMiddleware(thunk, promise, logger)
);
redux-thunk
actions.js
import fetch from 'isomorphic-fetch';
export const REQUEST_POSTS = 'REQUEST_POSTS';
function requestPosts(topic) {
return {
type: REQUEST_POSTS,
topic
};
}
export const RECEIVE_POSTS = 'RECEIVE_POSTS';
function receivePosts(topic, json) {
return {
type: RECEIVE_POSTS,
topic,
posts: json.data.children.map(child => child.data),
receivedAt: Date.now(),
};
}
function fetchPosts(topic) {
// return function instead of action object for thunk middleware
return (dispatch) => {
// start request
dispatch(requestPosts(topic));
// return Promise object as the return value of the dispatch method
return fetch(`service/${topic}.json`)
.then(response => response.json())
.then(json => dispatch(receivePosts(topic, json)));
};
}
function shouldFetchPosts(state, topic) {
const posts = state.postsByTopic[topic];
if (!posts) {
return true;
} else if (posts.isFetching) {
return false;
} else {
return posts.didInvalidate;
}
}
exports function fetchPostsIfNeeded(topic) {
return (dispatch, getState) => {
if (shouldFetchPosts(getState(), topic)) {
// dispatch a thunk from thunk
return dispatch(fetchPosts(topic));
} else {
// let the calling code know there is nothing to wait for
return Promise.resolve();
}
};
}
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
initialState,
applyMiddleware(thunk)
);
redux-promise
const fetchPosts = (dispatch, topic) => new Promise(function (resolve, reject) {
// start request
dispatch(requestPosts(topic));
// return Promise object as the return value of the dispatch method
return fetch(`service/${topic}.json`)
.then(response => response.json())
.then(json => dispatch(receivePosts(topic, json)));
});
import { createStore, applyMiddleware } from 'redux';
import promise from 'redux-promise';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
initialState,
applyMiddleware(promise)
);
Redux 入门教程(三):React-Redux 的用法 - 阮一峰的网络日志
this.state
this.props
this.state
connect()
import { connect } from 'react-redux';
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps,
)(TodoList);
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
http://zhenhua-lee.github.io/img/state-mge/mobx.png
How We Ditched Redux for MobX – Skillshare Writings – Medium
https://cdn-images-1.medium.com/max/1000/1*QZ8X8IZfm7IPkZj0iyRC7w.png
MobX vs Redux with React: A noob’s comparison and questions
react 的数据管理方案:redux 还是 mobx? - 腾讯Web前端 IMWeb 团队社区 | blog | 团队博客
使用 mobx 时,借鉴了 redux 架构的优点:
store
actions
可以在子组件中,通过 props
访问使用不同点:
@inject
装饰器语法注入,redux 使用的是 connect
语法注入@observer
语法,让一个 component 能响应 store
字段更新connect
参数手动控制传递哪些字段store
的状态,但是必须在 @action
修饰的函数中完成,@action
的语义,表示这是一个修改状态的操作Provider
传递 store
是强约定,mobx Provider
灵活传递 store
actions
,也可以是其它名字,比如 db
connect
combineReducers
bindActionCreators
mapStateToProps
mapDispatchToProps
,mobx 方案,除了使用 decorator
语法,没有其它让人感觉理解困难的函数。actions
直接改变数据Redux:
dispatch
都会导致广播,需要依据对象引用是否变化来控制更新粒度。immutable
。action
与 reducer
完全脱节,数据流过程需要自行脑补。原因是可回溯必然不能保证引用关系。Mobx:
immutable
,也没有复制对象的额外开销。action
分发到 reducer
的过程)。Vuex与Redux对比 - hyupeng1006的博客 - CSDN博客
DVA,对React-Redux进行了封装,并结合了Redux-Saga等中间件,而且使用了model概念,也相当于在React-Redux的基础上针对web应用开发做了优化。(个人认为DVA框架的开发者可能是对VUEX有所借鉴的)
React – A JavaScript library for building user interfaces
weekly/079.精读《React Hooks》.md at v2 · dt-fe/weekly
import React, { useState } from 'react';
useState
is a React function that returns two things: a value and a function to change that value.
const [date, setDate] = useState(initialDate);
function tick() {
setDate(new Date());
}
<p>It is {date.toLocaleTimeString()}.</p>
import React, { useEffect } from 'react';
useEffect(() => {
// mount hook
const timerId = setInterval(() => tick(), 1000);
// return unmount hook
return () => clearInterval(timerId);
});
<button onClick={handleClick}>
Activate Lasers
</button>
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
React Hooks vs. Redux: Do Hooks and Context replace Redux? - LogRocket Blog
Context is designed to share data that can be considered “global” for a tree of React components.
React.createContext(defaultValue)
theme-context.js
import React from 'react';
// Create a context for the current theme (with "light" as the default).
export const ThemeContext = React.createContext('light');
Context.Provider
Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes.
Accepts a value
prop to be passed to consuming components that are descendants of this Provider.
Use a Provider to pass the data to the tree. Any component can read it, no matter how deep it is.
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
useContext
hook
All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.
themed-button.js
import { useContext } from 'react';
import { ThemeContext } from './theme-context';
function ThemedButton() {
const theme = useContext(ThemeContext);
return <Button theme={theme} />;
}
export default ThemedButton;
Pass a function down through the context to allow consumers to update the context.
theme-context.js
import React from 'react';
export const ToggleThemeContext = React.createContext(() => {
});
theme-toggler-button.js
import { useContext } from 'react';
import { ThemeContext, ToggleThemeContext } from './theme-context';
function ThemeTogglerButton() {
const theme = useContext(ThemeContext);
const toggleTheme = useContext(ToggleThemeContext);
return (
<button
onClick={toggleTheme}>
Toggle Theme
</button>
);
}
export default ThemeTogglerButton;
app.js
import { useState} from 'react';
import { ThemeContext, ToggleThemeContext, themes } from './theme-context';
import ThemeTogglerButton from './theme-toggler-button';
function App() {
const [theme, setTheme] = useState(themes.light);
function toggleTheme() {
setTheme(currentTheme => {
return currentTheme === themes.dark
? themes.light
: themes.dark
});
}
return (
// have to be nested Providers
<ThemeContext.Provider value={theme}>
<ToggleThemeContext.Provider value={toggleTheme}>
<Content />
</ToggleThemeContext.Provider>
</ThemeContext.Provider>
);
}
function Content() {
return (
<div>
<ThemeTogglerButton />
</div>
);
}
ReactDOM.render(<App />, document.root);
adam-golab/react-developer-roadmap: Roadmap to becoming a React developer in 2018
React 技术栈系列教程 - 阮一峰的网络日志