Address of original text: address of original text

Recently, I had time on the weekend to record my understanding of React and Redux after joining the front end for one year. Nothing is more convincing than a product. Here I set up a simple framework for young people who just joined the front end and prepared to learn React as a beginner. I hope those who have read it can give me some advice. I would appreciate it. Project code, there will be an upgrade later. To initialize a scaffold using create-react-app, see here for a tutorial.

Yarn add babel-plugin-transform-decorators-legacy-d, which adds the dependencies to the devDependencies of package.json. The first one is for development only and the second one is for production. So packages that are not available in production can be added directly to the first one.

Here are the total packages that need to be installed. I’ll try to talk about what each of them does, and try to introduce as few packages as possible to make the system lighter.

Depend on the package

Yarn Add ANTd Install ANTD

yarn add babel-plugin-transform-decorators-legacy -D

Yarn add Babel -preset-env -d. Babelrc Configuration is required

yarn add babel-plugin-transform-runtime -D

Yarn add babel-plugin-import -d After the configuration, you can import modules. For details, see the official website

yarn add babel-preset-stage-0 -D

Yarn add Babel -cli -d: yarn add Babel -cli -d: yarn add Babel -cli -d yarn add react-router-dom

After the dependency packages are installed, create a new.babelrc directory under the root directory to override some of esLint’s default actions. Create a.babelrc file

{ "presets": ["env", env includes es2015,2016,2017, "env", "react", "stage-0", "stage-0", "stage-0" ] [["transform-runtime" helpers: false, "polyfill" helpers: false, "polyfill" helpers: false, "polyfill" helpers: false, "polyfill" helpers: false, "polyfill" helpers: false, "regenerator": True}], "transform-decorators-legacy", can use the decorator ["import", antD is recommended to use this method, otherwise antD will not be able to use the module on demand {"libraryName": "antd", "libraryDirectory": "es", "style": "css" } ] ] }Copy the code

This will ensure that no errors are reported at compile time, but you will see a small red line under the method or class that is decorated by the decorator, so that you can create a new jsconfig.json under the root directory

Create a jsconfig.json file

{
    "compilerOptions": {
        "experimentalDecorators": true,
        "target": "es2017"
    },
    "exclude": [
        "node_modules",
        "dist"
    ],
    "include": [
        "src",
        "env",
        "static"
    ]
}
Copy the code

Creation-react-app uses antD as its default reference package, but it also uses ANTD as its default reference package. Then the project needs react-Redux and related resource packs.

    "react-redux": "^ 5.0.6"."react-router-redux": "^ 4.0.8"."redux": "^ 3.7.2." "."redux-actions": "^ 2.2.1." "."redux-devtools-extension": "^ 2.13.2"."redux-thunk": "^ 2.2.0." ".Copy the code

That’s all you need to do. When you’re ready, it’s time to start. Speaking of Redux, if it’s not clear, this is the best introduction to Redux I’ve ever read. Then, will enter the actual link, the new Action under the SRC directory, components, containers to store network request/Action, components and page container. Create createFetchAction.js in the Action directory as a tool class to access the web. If you are interested, refer to my code. I have made a very detailed comment. Then look at the code inside the store:

Const composeEnhancers = composeWithDevTools({// Options like actionSanitizer, stateSanitizer }); const middleware = [thunk]; // This is a load of middleware that can add a lot, but also provides unlimited extensibility and possibilities for implementing functions. const store = createStore(combineReducers({routering: RouterReducer}), // This is the imported default route {}, composeEnhancers(applyMiddleware(... middleware) )); Store. AppReducers = {} // Global reducerexport const updateReducer = (key,reducer) => {
    if (Object.hasOwnProperty.call(store.appReducers, key)) return; store.appReducers[key] = reducer; The current Reducer can be added to the global reducer with each call. The routerReducer is the introduced initial state, or you can define a local reducer and add it when the project starts. store.replaceReducer(combineReducers({routering: routerReducer ,... store.appReducers})); }export default store;
Copy the code

The entry point to the project is the app.js file, which configures the route and its corresponding component to display.

    async  componentDidMount() {object.keys (reducers).foreach (name=>{// Add all reducer files to 'appReducers' at the start of the project updateReducer(name,reducers[name]); }); }render() {
		return<Provider store={store}> <div style={{width:'100%'}}> <Switch> Only one component in the Switch can be loaded at the same time. Check <Route path= from top to bottom'/login' component={APP.LOGIN} />
							<Route path='/page404' render={() => {
								return(<h1>404 not found</h1>); }} /> <Redirect from='/' to='/page404'/> Redirect url </Switch> </div> </BrowserRouter> </Provider>); }Copy the code

As you can see above, the Login component is introduced, so create a new login.js file in the containers. There will be login verification code in this file. Forget about it for now. I have set up a Node server locally and this process will be added to the itemized list later.

Let’s talk more about Action creation:

I won’t go into the index.js export, but here are the two files under the login folder:

index.js
[combineActions(...getValuesFromObj(actions))]:(state = {},action)=>{
    return{... state,... LoginReducer (state, action) this... The loginReducer contains a reducer that is exported from login.js, and each time an action with the same name is called from the page, for examplesetLoginData is going to go over here to callsetFor LoginData, it returns the combination of the current state and LoginData. This is also the core of Redux, which is only updated at a time and cannot be modified. } } login.js constsetLoginData = createAction('the login action');
const setLoginData1 = createAction('testing action');
const getAllEmployeeOk =  createAction('Get all users'); // The getAllEmployeeOK function will be called after the call is successful. const getAllEmployee = createAsyncAction('http://localhost:8080/tabledata'.'GET',getAllEmployeeOk);

export const actions = {
    setLoginData,
    setLoginData1,
    getAllEmployee,
    getAllEmployeeOk 
}
export default handleActions({
    [setLoginData]: (state, {payload}) => ({
        loginData: payload
    }),
    [setLoginData1]: (state, {payload}) => ({
        loginData1: payload
    }),
    [getAllEmployeeOk]:(state,{payload})=>{
        return{
            employee:payload
        }
    }
},{});
Copy the code

Login. js defines functions and exports them. The operations in index.js further split the exported login.js contents. For example, login is counted as one, and an uncreated register can also be counted as one. The actions are exported using handleActions. This is equivalent to registering the Reducer and updating the redux values according to the reducer rules when the actions are called in the page methods. GetValuesFormObj is officially available in ActionsMap, but to illustrate its nature, I wrote a castrated version of it myself. This component just shows the username and password input fields, and then does a little test of Redux in componentDidMount and click events.

@connect(state => {this state is the global state, and you can filter it out here to say that you only want part of the store value.returnstate; The returned state is mapped to Props, which can be accessed via this. Props. If you want to access part of it, you canreturnState.login {if there is such a branch}, dispatch => ({//bindThe ActionCreators function provides the Dispatch parameter for the action created through createAction. Knowing that the Action cannot be called without Dispatch, and that connect helps us out, Add all actions [and network access-related] to props bindedActions:bindActionCreators({ ... actions }, dispatch), }) )componentDidMount () {
    const { setLoginData1 } = this.props.bindedactions;
    setLoginData1('123'); After this call, there is an additional record in the Store of redux, and you can print this. Props to confirm. }Copy the code