Redux core concepts

  Redux used for state management, there are three basic principles

  1, regardless of the state of simple or complex the application, the state of the entire application (state) only in the presence of a common js object, the object known state tree. Simple state, such as a counter application, it is only a state

const state = 0;

  Complex state, such as a list of users, state probably contains an array of objects

const state = [
    {
        id: 1,
        name: 'sam',
        age: '20'
    },
    {
        id: 2,
        name: 'josn',
        age: '21'
    }
]

  2, the state is read-only state, we can not directly change state. The only way to change the state of the transmission (dispatch) an action. action is also a common js object that is used to describe how to change the state, so it must have a specified type attribute, what kind of change type to describe the state going to do, what kind of operation you want to perform for the state. Usually type a string description of the action, such as 'increment', increment represents an increase, one can see this type, you know what kind of changes the state to do.

{
    type: 'increment'
}

  How much does it increase? action can carry data ah! aciton just a js objects, in addition to the required type, you can add any of the property, you want to carry data (increase number) as another property just fine.

{
    type: 'increment',
    wantAddNum: 10
}

  action becomes a carrier which passes the data to the application state.   

  3, change the state, the use of pure function reducer. Action as an ordinary object, is unlikely to change its own state of another object, action merely describes an action, specifically how to change the status of this operation, it no matter what. How does that change the state? Is also very simple, you might have thought, is to write a function, the function can accept the object as a parameter, then operate on the object and returns a new object. The state and the action it can pass a function to calculate the new state., This function is called reducer. Here we must note, reducer is a pure function, do not change the parameter passed in the state, never to be returned the new state object.

function counter(state, action) {
    switch (action) {
        case 'increment': 
            return state + action.wantAddNum;
        default:
            return state;
    }
}

   Well, now we have two objects state and action, a function reducer, that these three unrelated content is how to link together? Who will dispatch action dispatch? After dispatch atcion, how to reducer it in? reducer in addition to action, there is a state, it is how to get the state? These questions point to the core Redux Another object store. Of course, store does not appear out of thin air, we need to create. Redux createStore library exposes a function that takes reducer and then return to store.

  When the time reducer as a parameter, internal createStore reducer function can certainly call to change the state, and that is how aciton and transferred to the state createStore inside, reducer for use. First, action, Store objects returned createStore exposes a dispatch method, which takes action, store.dispatch (action). This put into the transfer action. state how spread createStore inside, more accurate to say that the initial state, the initial state of how the entire application delivery to createStore inside? There are two ways, the simplest one is createStore function can accept an optional parameter intialState, directly to the initial state passed in it. So far createStore to get inside the action, state, and reducer, finally joined together, can change the state.

  But this raises another question, state changes, the outside world is how to get it? Or to find store object that has a method, store.getState (), that when I call getState () to get the state after the update it? Because after dispatch action, redux update state is uncertain, it may take a long time? The last method store object, subscribe (), which takes a callback function, you can call getState in this function () to get the updated status. As long as a dispatch action, application status changes, subscribe callback will be executed to ensure that access to the latest state. Redux now the whole process is complete.

  According to the description, we can write a simple redux, it is to have a createStore function that takes reducer, intialState as a parameter and returns a object that has getState (), subscribe (), dispatch () method

createstore function (the reducer, the initialState) { 
    the let the currentState = the initialState; // store the internal state of 
    the let the Listeners = [];   // store listening function (callback function in subscribe) 

    function getState () { 
        return the currentState; 
    } 

    function subscribe (listener ) { 
        listeners.push (listener); 
    } 

    function dispatch (Action) { 
        the currentState = the reducer (the currentState, Action);
         // after dispatch action, state change, all listening function is done. Using forEach 
        listeners.forEach (listener => listener ()); 
    } 

    return  {getState, Subscribe, dispatch};
}

  So, for Redux development, first of all want a good state, which state action and applications have, what to do to change the operating state. Then reducer, according to our action how to deal with state. With After reducer, createStore create the store, you can then use store.dispatch to update the status, store.subscribe and store.getState () to get the updated status.

  Having said that theory, practice what you can, and write a simple counter, click the plus sign, add 1, click the minus, minus 1, and finally there is a reset button. Without interference to other frameworks and libraries, where the use of pure HTML, script tags with reference Redux, when introduced using a script tag Redux library, there will be a property of the window object Redux. Create a rudex.html, and introducing bootstrap css redux and writing a new counter.js js code, html files as follows

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>redux</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/redux/4.0.4/redux.js"></script>
</head>
<body style="text-align: center">
    <!-- 显示状态 -->
    <h1 id="counter">0</h1>
    <button type="button" class="btn btn-primary" id="add">Add</button>
    <button type="button" class="btn btn-success" id="minus">Minus</button>
    <button type="button" class="btn btn-danger" id="reset">Reset</button>
    <script src="./counter.js"></script>
</body>
</html>

   Began to write js code, first of all would like to state, state is very simple, it is a counter, can be initialized to 0, then the shape and state would look initialState

const initialState = {
    counter: 0
}

  Think of action, three buttons, an add, a subtract, a reset function is different, then three action 

// action 
const add = {
    type: 'ADD'
}
const minus = {
    type: 'MINUS'
}

const reset = {
    type: 'RESET'
}

  Then the reducer, respectively, plus 1, minus 1, reset to an initial state

// reducer, chrome 直接支持... 操作对象
function counter(state, action) {
    switch(action.type) {
        case 'ADD': 
            return {
                ...state,
                counter: state.counter + 1
            }
        case 'MINUS':
            return  {
                ...state,
                counter: state.counter - 1
            }
        case 'RESET':
            return {
         ...state, 
         counter: 0
       };
default: return state; } }

  Through this simple reducer, and then repeat the precautions reducer. reducer must return a new object, rather than modify the parameters of state, even if you change, Redux will ignore any changes you make. Furthermore, since the reducer must return a new state object is to replace the old state, so all the attributes of the old state must be copied to the new state, the simplest way of copying is to use ... delimiter. Then action which you want to change a property status, write directly to the following delimiter as properties of the new state of the object, give it to assign a new value, which would overwrite the value of the property in the old state, the state of completion of the update .

  With reducer, you can create a store.

const store = Redux.createStore(counter, initialState);

  Now you can click a button, dispatch action a. Three button click event to bind to dispatch action. 

document.getElementById('add').addEventListener('click', () => {
    store.dispatch(add);
})

document.getElementById('minus').addEventListener('click', () => {
    store.dispatch(minus);
})


document.getElementById('reset').addEventListener('click', () => {
    store.dispatch(reset);
})

  The final step is to obtain state, the feedback page, register a listener function subscribe method, this function is only responsible for the latest status assigned to page elements.

const stateDiv = document.getElementById('counter');
function render() {
    stateDiv.innerHTML = store.getState().counter;
}
store.subscribe(render)

  Now we make a simple change, the element content 0 <h1 id = "counter"> removed, obtaining it directly from the initial value of the state. Then the conter to 5 initialState

<h1 id="counter"></h1>
const initialState = {
    counter: 5
}

  Refresh the page, you will find that there is no status display on the page. This is how the same thing? Because we did not render state to elements on the page, we only define the render function, and is called in subscribe, because no click trigger state changes, subscribe to perform a function and will not, we can only call once to manually render function . Once, render (), and then refresh in store.subscribe (render) manually call the following pages, you will find the status display 5, that status has become store inside the 5. It is how the initial state into a store inside the state? In fact, when createStore create store objects, internal Redux dispatch an action ( "@@ redux / INIT"), action triggers, and will definitely call counter reducer, the reducer because we do not deal with this action, it's gone switch the default branch , also said that in creatorStore time, defualt branch reducer will always be called in. This gives us a second way of initializing state, provide default values ​​directly in the default branch, or use the default parameters of Es6 .

// reducer, chrome 直接支持... 操作对象
function counter(state = initialState, action) {
    switch(action.type) {
        case 'ADD': 
            return {
                ...state,
                counter: state.counter + 1
            }
        case 'MINUS':
            return  {
                ...state,
                counter: state.counter - 1
            }
        case 'RESET':
            return {
         ...state, 
         counter: 5
       };
        default:
            return state;
    }
}

  In this case createStore process can initialState removed.

const store = Redux.createStore(counter);

  This is also the time of writing reduer to note one point, each reducer must have a default branch, namely the provision of action is not treated, the second is to provide the initial value of the entire store.

Guess you like

Origin www.cnblogs.com/SamWeb/p/11311358.html