preface

If you want to see the theory of children click here redux Chinese document or redux official document, this article will not deliberately introduce a large length of theory, this article does not make a comparison between the framework, only for children who want to learn Redux to provide substantive, efficient, easy to understand the learning reference resources, share their own learning process. The article will be longer after the update, please be patient to read and understand, carefully taste. It doesn’t matter if you are not familiar with Redux, you can follow the article ideas and finish the three demos. I believe you will benefit a lot. (The egg is painted after the article.)

Updated content

  • reduxBasic use (with demo)
  • redux MiddlewareUse (with demo)
  • reduxintegrationnavigation(demo)

Todos
react native

async
react native

Integrate the first two DOMOs with react-native navigation.

Content to Be Updated

  • To be continued…

Why am I writing this demo

Some children may have doubts

Q: Isn’t the official Todosdemo? Why did I write this demo?

A: Official Demos are react, not React Native. I also looked for a lot of articles about Redux, but I found that the materials I found were too basic or not comprehensive, the demo download didn’t work, etc., and I was motivated to build my own wheel, and this demo wasn’t just about the basics of Redux. But through three sets of demo practice coherent graphics, let readers better understand, later will be updated in the process of using Redux, hope you encourage support.

Code specification used by Demo

A large project usually involves many developers at the end of the project, and if each developer uses his or her own set of code specifications, the result will be: Late code management is a hassle, takes more time to refactor, takes more time for new people to understand the code, and drives people away, so a large project has to follow some specifications when it’s first architecting.

So how can we type clean and elegant code? How do we check the quality of our code? I highly recommend following the Airbnb /javascript spec and using ESLint to check the quality of your code as they have been approved by many companies and developers. (There is too much introduction to Airbnb ESLint, this article only provides ideas, want to know more search by yourself)

Without using code specification before we could use their own style to write the code for many years, suddenly want to adapt to this specification may be very not adapt, it doesn’t matter, more practice more, time grew to become accustomed to, who is not a process, the process is bitter, but the pain after brings qualitative sublimation, slowly understand understand yourself. Good things will be accepted by the world, and bad things will eventually be replaced, so as a qualified programmer (especially front-end programmers) embrace change, because it will make you better and get accepted by the public, unless you don’t want to make yourself better.

What can Redux do for us

Two pictures:

Story features

  • Single data source: for the entire applicationstateIs stored in an object tree and exists in only one object treestoreIn the.

  • State is read-only: the only way to change State is to triggeractionAction is a generic object that describes events that have occurred.

  • Use pure functions to perform modifications: To describe how an action changes the state tree, you need to writereducers.

  • Predictability: All user behavior is defined in advance by you.

  • Unified management state: All states are allocated and managed in a store.

Which developers and projects are suitable for Redux

For react Native development only:

  • I don’t recommend using React Native because you don’t know how to use it. It is recommended to reach intermediate level first.

  • Intermediate: Use React Native to create one or more uncomplicated redux applications that are already on the market, or don’t use them, because using redux doesn’t allow you to develop quickly and iteratively up front. Using Redux on projects like this is like shooting a cannon at a mosquito with a lot of side effects. But you can understand it first and find its advantages. This is a relatively simple application: when the user triggers an action (the application needs setState({XXX: XXX})), the application state flow looks like this:

  • Advanced: Use React Native to create a complex application that is already on the shelves (involving im, complex interface layout, too many layers of nested components, etc.). When the user triggers an action (setState({XXX: XXX})), the application state flow looks like this:

The consequences of this state are analyzed from two aspects:

  • Performance: Redundant state passing between subcomponents leads to a waste of valuable memory resources, while the interface renders slowly, resulting in a poor user experience.
  • State management: As the program iterates and the interface layout becomes more and more complex, it is inevitable that manystateStates, how do you manage those states effectively? What causes the UI to render multiple times? Which action caused the change in the UI component? In no usereduxPreviously you may have found that you can use the life cycle functionshouldComponentUpdateTo reduce unnecessary rendering in child components, but ultimately does not solve the complex problem of state management. When you usereduxAfter that, the complex application state flow looks like this:

    After reading the above pictures and pictures, do you have an intuitive understanding of what kind of project is suitable for redux? Thank you@justjavacGIF support provided by the article.

Redux for React Native working logic diagram

Thanks to @Blackforest Studio author for the clear logic diagram

Redux engineering structure analysis

I made some changes to the official demo in a small part of the location to see the code analysis:

The division of subsidiary

  • js/actionsWhat this folder does is define user behavior.
  • js/reducersWhat this folder does is respond to the user’s behavior, return the changed state, and send itstore.
  • js/componentsHere’s what this folder does: custom components.
  • js/containersThis folder drops content to do the followingcomponentsComponents in the folder that are involved in state changes are encapsulated a second time.
  • App.jsThe entry file (Store is here), why do I define store here? Because it is unique and must be usedreact-reduxTo provide theProviderComponent package entry for other componentsreduxIn thestoreTo take effect.
  • global.jsStore globally defined variables, constants, methods, etc.

Something to watch out for

  • In a projectreduxstoreBe unique and cannot be in multiplestore
  • keepreducerPurity is very important. Never in the worldreducerTo do these operations:
  • Modify the passed parameter;
  • Perform operations that have side effects, such asAPIRequest and route hops;
  • Call an impure function, such asDate.now()Math.random();
  • Use the object expansion operator.Instead ofObject.assign()Is the best solution.
  • The component name must be capitalized, i.ecomponentsandcontainersAll files in folders should begin with a capital letter.
  • You should minimize pass-through toactionData in (can transmit a data do not pass object, can transmit an object do not pass array)
//good
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}
Copy the code
//best
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return { ...state, visibilityFilter: action.filter }
    default:
      return state
  }
}
Copy the code

Code,

js/actions/types.js

// Add list dataexport const ADD_TODO = 'ADD_TODO'; / / filterexport const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'; // Add/ununderline textexport const TOGGLE_TODO = 'TOGGLE_TODO';
Copy the code

Shih:

The action definition

Why should I separate out the user’s action definition and write type.js?

  • Convenient state management.
  • Reusability.

js/actions/index.js

import  {
    ADD_TODO,
    SET_VISIBILITY_FILTER,
    TOGGLE_TODO,
} from './types'
let nextTodoId = 0;

export const addTodo = text => ({
    type: ADD_TODO,
    id: nextTodoId++,
    text
});

export const setVisibilityFilter = (filter) => ({
    type: SET_VISIBILITY_FILTER,
    filter
});

export const toggleTodo = id => ({
    type: TOGGLE_TODO,
    id
});
Copy the code

Shih:

Action create function

The Action creation function is the method that generates the Action. The concepts of “action” and “action creates a function” are easily confused and are best distinguished when used.

The action creation function in Redux simply returns an action:


js/reducers/todos.js

import  {
    ADD_TODO,
    TOGGLE_TODO,
} from '.. /actions/types'

const todos = (state = [], action) => {
    let {id, text, type} = action;
    switch (type) {
        case ADD_TODO:
            return [
                ...state,
                {
                    id: id,
                    text: text,
                    completed: false}];case TOGGLE_TODO:
            returnstate.map(todo => (todo.id === id) ? {... todo, completed: ! todo.completed} : todo); default:returnstate; }};export  default  todos;
Copy the code

js/reducers/visibilityFilter.js

import { SET_VISIBILITY_FILTER } from '.. /actions/types'
import { visibilityFilters } from '.. /global'

const { SHOW_ALL } = visibilityFilters;
const visibilityFilter = (state = SHOW_ALL, action) => {
    let {type, filter} = action;
    switch (type) {case SET_VISIBILITY_FILTER:
            return filter;
        default:
            return state
    }
};

export default  visibilityFilter;
Copy the code

Shih:

reducerIt’s a pure function that accepts the oldstateaction, return newstateThe above two files can look at tworeducer).

Note:

  • ReduxThe first time I do it,stateundefinedIn this case, you need to set to return to the initial applicationstate.
  • eachreducerJust managing the big picturestateFor which it is responsible. eachreducerstateThe parameters are different, corresponding to the part it managesstateThe data.

js/reducers/index.js

import { combineReducers } from 'redux'
import todos from './todos'
import visibilityFilter from './visibilityFilter'

export default combineReducers({
    todos,
    visibilityFilter
})
Copy the code

Shih:

combineReducers()All you do is generate a function that calls your seriesreducer, eachreducer Filter them out by their keystatePart of the data and processingAnd then the generated function takes all of thereducerMerges the result into one large object.

The seemingly combineReducers() function is to combine multiple reducers into a reducer.


js/components/Todo.js

import React, { Component } from 'react'
import {
    Text,
    TouchableOpacity
} from 'react-native'
import PropTypes from 'prop-types'

export default class Todo extends Component {
    static propTypes = {
        onClick: PropTypes.func.isRequired,
        completed: PropTypes.bool.isRequired,
        text: PropTypes.string.isRequired
    };

    render() {let { onClick, completed, text } = this.props;
        return (
            <TouchableOpacity
                style={{
                    flexDirection: 'row',
                    flex: 1,
                    height: 50,
                    alignItems: 'center',
                    justifyContent: 'center',
                    backgroundColor: '#cccccc',
                    marginTop: 10
                }}
                onPress={onClick}>
                <Text style={{ textDecorationLine: completed ? 'line-through' : 'none'}}>{text}</Text> </TouchableOpacity> ); }}Copy the code

js/components/TodoList.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
    FlatList
} from 'react-native'
import Todo from './Todo'

export default class TodoList extends Component {
    static propTypes = {
        todos: PropTypes.arrayOf(
            PropTypes.shape({
                id: PropTypes.number.isRequired,
                completed: PropTypes.bool.isRequired,
                text: PropTypes.string.isRequired
            }).isRequired
        ).isRequired,
        toggleTodo: PropTypes.func.isRequired
    };

    _renderItem = (data) => {
       let dataItem = data.item;
       let { id } = dataItem;
       let { toggleTodo } = this.props;
        return( <Todo {... dataItem} onClick={() => toggleTodo(id)} /> ) };render() {
        let { todos } = this.props;
        return (
            <FlatList
                data={todos}
                keyExtractor={(item)=>item.id.toString()}
                renderItem={this._renderItem}
            />
        )
    }
}
Copy the code

js/components/Link.js.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
    TouchableOpacity,
    Text
} from 'react-native'

export default class Link extends Component {
    static propTypes = {
        active: PropTypes.bool.isRequired,
        filter: PropTypes.string.isRequired,
        onClick: PropTypes.func.isRequired
    };

    render() {
        let { active,  filter, onClick } = this.props;
        return (
           <TouchableOpacity
               style={{
                   marginLeft: 4,
                   height: 40,
                   flex:1,
                   borderWidth: 1,
                   borderColor: '#ccc',
                   alignItems: 'center',
                   justifyContent:'center'
               }}
               onPress={onClick}
           >
               <Text style={{fontSize: 10, color: active ? 'black' : '#cccccc'}}>{filter}</Text> </TouchableOpacity> ); }}Copy the code

js/components/Filters.js

import React, { Component } from 'react'
import {
    View,
} from 'react-native'
import FilterLink from '.. /containers/FilterLink'
import { visibilityFilters } from '.. /global'

const { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE  } = visibilityFilters;

export default  class Filters extends Component {

    render() {return(
            <View style={{ flexDirection: 'row', marginTop: 20}}>
                <FilterLink filter={SHOW_ALL} />
                <FilterLink filter={SHOW_COMPLETED} />
                <FilterLink filter={SHOW_ACTIVE} />
            </View>
        )
    }
}
Copy the code

Shih:

The above four files are four custom UI presentation components that define the look and feel regardless of where the data comes from and how it changes. Render what is passed in. If you take the code fromReduxWhen you migrate to another architecture, these components can be used without any changes. They don’t depend onRedux.


js/containers/AddTodo.js

import React, { Component } from 'react'
import {
    View,
    TextInput,
    Button,
} from 'react-native'
import { connect } from 'react-redux'
import { addTodo } from '.. /actions'

class AddTodo extends Component {
    constructor(props){
        super(props);
        this.inputValue = ' ';
    }

    render() {let { dispatch } = this.props;
        return (
            <View style={{flexDirection: 'row'}}>
                <TextInput
                    style={{flex:1, borderWidth: 1, borderColor: '#cccccc', textAlign: 'center'}}
                    onChangeText={text => this.inputValue = text}
                />
                <Button title="Add Todo" onPress={() => dispatch(addTodo(this.inputValue))}/>
            </View>
        )
    }
}

export default connect()(AddTodo)
Copy the code

js/containers/FilterLink.js

import { connect } from 'react-redux'
import { setVisibilityFilter } from '.. /actions'
import Link from '.. /components/Link'

const mapStateToProps = (state, ownProps) => ({
    active: ownProps.filter === state.visibilityFilter,
    filterText: ownProps.filter
});

const mapDispatchToProps = (dispatch, ownProps) => ({
    onClick: () => dispatch(setVisibilityFilter(ownProps.filter))
});

export default connect(
    mapStateToProps,
    mapDispatchToProps,
)(Link)
Copy the code

js/containers/VisibleTodoList.js

import { connect } from 'react-redux'
import { toggleTodo } from '.. /actions'
import TodoList from '.. /components/TodoList'
import { visibilityFilters } from '.. /global'

const { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } = visibilityFilters;

const getVisibleTodos = (todos, filter) => {
    switch (filter) {
        case SHOW_COMPLETED:
            return todos.filter(t => t.completed);
        case SHOW_ACTIVE:
            returntodos.filter(t => ! t.completed);case SHOW_ALL:
            return todos;
        default:
            throw new Error('Unknown filter: ' + filter)
    }
};

const mapStateToProps = state => ({
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
});

const mapDispatchToProps = dispatch => ({
    toggleTodo: id => dispatch(toggleTodo(id))
});

export default connect(
    mapStateToProps,
    mapDispatchToProps,
)(TodoList)
Copy the code

Shih:

The above three are container components that connect the presentation component to Redux. Bottom line: Just remember one thing: the UI presentation component is responsible for rendering the UI, and the container component is responsible for managing the data and logic. Sometimes it’s hard to tell whether to use container components or presentation components. Such as this small component:

  • AddTodo.jsContains an “Add” button and input box

It’s technically possible to split it into two components, but it’s a little early to start. It is possible to mix containers and presentations in very small components. As businesses get more complex, it becomes obvious how to break them up. So go for the hybrid now.

The react-Redux connect() method is used to associate presentation and container components together, which is optimized to avoid many unnecessary duplicate renderings. (This way you don’t have to manually implement the shouldComponentUpdate method in the React performance optimization suggestion for performance.)

Before using connect(), you need to define the function mapStateToProps to specify how to map the current Redux store state to the props of the presentation component. For example, VisibleTodoList needs to evaluate todos passed to TodoList, so a method to filter state.todos based on state.visibilityFilter is defined and used in mapStateToProps.

In addition to reading state, container components can also distribute actions. In a similar manner, the mapDispatchToProps() method can be defined to receive the Dispatch () method and return the callback method expected to be injected into the props of the presentation component. For example, we want VisibleTodoList to inject a props called onTodoClick into the TodoList component, and we want onTodoClick to distribute the TOGGLE_TODO action. Finally, create the VisibleTodoList using connect() and pass in both functions.


js/components/Group.js

import React, { Component } from 'react'
import {
    View
} from 'react-native'
import AddTodo from '.. /containers/AddTodo'
import Filters from '.. /components/Filters'
import VisibleTodoList from '.. /containers/VisibleTodoList'

export default class Group extends Component {
    render() {
        return( <View style={{paddingHorizontal: 20, paddingVertical: 44}}> <AddTodo/> <Filters/> <VisibleTodoList/> </View> ); }}Copy the code

Shih:

Group.jsIt is to string all the associated components together to form a complete interface.


App.js

import React, { Component } from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import Group from './js/components/Group'
import rootReducer from './js/reducers'

export default class App extends Component {
    render() {
        const store = createStore(rootReducer);
        return( <Provider store={store}> <Group /> </Provider> ); }}Copy the code

Shih:

Import file incomingStore

  • createstoreThe incomingreducers.
  • useProviderThe component packageGroupComponents,storePassed in as an attributeProvider.

At this point, the code analysis is complete. This is the end of this writing. I believe that if you read carefully, more or less there will be some harvest, if the demo does not understand, then follow the idea of code analysis to type the code several times, also understand, I will continue to update the unfinished content.

~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️

⭐️⭐ ⭐ ⭐ ⭐️⭐ ⭐ ⭐️⭐️ disk disk disk disk disk disk disk disk disk disk disk disk disk

~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️

It’s been a couple of days since the last update, but today’s update is about Middleware.

The role of Middleware

Middleware is a tool that is embedded between Actions and Dispatcher to solve problems and improve our development efficiency. There are three common types of middleware:

  • Redux-thunk middleware: Asynchronous operations are needed in a project (e.g., requests for server data, local storage, etc.).
  • redux-actionsMiddleware: Helps process and create operationsactions(This is not covered in this article, but you can use it to create future projects when they are more complex).
  • redux-loggerMiddleware: Used for printingactionThe logs. openreact nativeRemote debug mode, operation demo can see the printed status changes in the console.

After the middleware is added, the schematic diagram is as follows:

Core code details

In order to reduce the length of the article, this demo code will only explain the parts involved in Middleware, that is to say, the demo will not explain too much about the new files added under the reducers, components and containers files. If you do not understand, You can go back and parse the first update again.

Add the following code to actions/types.js

// Request a list of postsexport const REQUEST_POSTS = 'REQUEST_POSTS'; // The post returns dataexport const RECEIVE_POSTS = 'RECEIVE_POSTS'; // Switch data sourcesexport const SELECT_SUBREDDIT = 'SELECT_SUBREDDIT'; // Invalidate the cacheexport const INVALIDATE_SUBREDDIT = 'INVALIDATE_SUBREDDIT';
Copy the code

The following code is added to actions/index.js

export const selectSubreddit = subreddit => ({
    type: SELECT_SUBREDDIT,
    subreddit
});

export const invalidateSubreddit = subreddit => ({
    type: INVALIDATE_SUBREDDIT,
    subreddit
});

export const requestPosts = subreddit => ({
    type: REQUEST_POSTS,
    subreddit
});

export const receivePosts = (subreddit, json) => ({
    type: RECEIVE_POSTS, subreddit, posts: json.data, receivedAt: Date.now() }); Const fetchPosts = subreddit => dispatch => {// API sends a request dispatch(requestPosts(subreddit));return fetch(`http://localhost:8081/data/${subreddit}.json`)
        .then(response => response.json())
        .then(json => {
            setTimeout(()=>{// Use API to request results to update application state dispatch(receivePosts(subreddit, json))},2000); })}; const shouldFetchPosts = (state, subreddit) => { const posts = state.postsBySubreddit[subreddit];if(! posts) {return true
    }
    if (posts.isFetching) {
        return false
    }
    return posts.didInvalidate
};

export const fetchPostsIfNeeded = subreddit => (dispatch, getState) => {
    if (shouldFetchPosts(getState(), subreddit)) {
        return dispatch(fetchPosts(subreddit))
    }
};
Copy the code

Interpretation of the

The main points to note above are

  • fetchPostsReturns a function while normalAction create functionAn object is returned by default.
  • The argument to the function returned isdispatchandgetStateThe twoReduxMethod, ordinaryAction create functionThe parameter isActionThe content of the.
  • Of the returned functions, emit oneAction: dispatch(requestPosts(subreddit)), indicating that the operation starts.
  • After the asynchronous operation is complete, issue anotherAction: receivePosts(subreddit, json)Is displayed, indicating that the operation is complete.

Data source description in Demo:

I originally intended to use the official Reddit Demo API, but finally found that the demo data provided by the official would report an error, so I used local JSON data and delayed the loading process of network API by two seconds.


App.js

import React, { Component } from 'react'
import { applyMiddleware, createStore } from 'redux'
import { createLogger } from 'redux-logger'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import LoadPosts from './js/containers/LoadPosts'
import rootReducer from './js/reducers'

export default class App extends Component {
    render() {
        const logger = createLogger();
        const store = createStore(
            rootReducer,
            applyMiddleware(thunk, logger)
        );

        return( <Provider store={store}> <LoadPosts/> </Provider> ); }}Copy the code

Interpretation of the

CreateStore now has a different parameter for applyMiddleware(Thunk, Logger). For those of you who understand the first update, you can see that the Action is sent by the store.dispatch method. In normal cases, the parameters of the store.dispatch method can only be objects, not functions. To solve this problem, the middleware Redux-thunk is used to modify store.dispatch to accept functions as arguments.

Pay attention to

Some middleware have order requirements, check the documentation before using it. For example, logger must be placed last, otherwise the output will be incorrect.


This is the end of this writing.

~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️

⭐️⭐ ⭐ ⭐ ⭐️⭐ ⭐ ⭐️⭐️ disk disk disk disk disk disk disk disk disk disk disk disk disk

~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️ ~ ️

If you’ve used older versions of React Native, you know that before react navigation came along, most developers used the official Navigator. Until react Native V0.44.3 announced that Navigator had been abandoned.

Navigator
react-navigation

  • react navigation

It’s officially recommended, available at 🌟 on Github and maintained by the React Native community. It’s currently the most popular React Native navigation library. It is written entirely in JavaScript, rather than using native apis, and it recreates some subsets. This option allows users to customize any part of the navigation experience without having to learn iOS or Android navigation logic. Since most of the React Navigation logic runs in JavaScript rather than native, anything that blocks the JavaScript thread will cause stuttering. React Navigation v1 is quite different from v2. If you want to know the children’s shoes can see in front of me to write this article [react native powerful navigation V2.0 +] (www.jianshu.com/p/05fd0e9bc)… .

At present, it has been clearly stated in official documents:

Warning: in the next major version of React Navigation, to be released in Fall 2018, we will no longer provide any information about how to integrate with Redux and it may cease to work. Issues related to Redux that are posted on the React Navigation issue tracker will be immediately closed. Redux integration may continue to work but it will not be tested against or considered when making any design decisions for the library.

Some folks like to have their navigation state stored in the same place as the rest of their application state. Think twice before you consider doing this, there is an incredibly good chance that you do not need to do this!. Storing your React Navigation state in your own Redux store is likely to give you a very difficult time if you don’t know what you’re doing.

If your only reason for doing this is that you want to be able to perform navigation actions from outside of your components (eg: from a Redux middleware), you can learn more about this in navigating without the navigation prop.

Translation:

Warning: In the next major release of React Navigation, due in fall 2018, we will no longer provide any information on how to integrate Redux, and it may be discontinued. Redux issues posted in React Navigation Issue tracker will also be closed immediately. The Redux integration may continue to work, but will not be tested or considered when making any design decisions for the Library.

Some people like to store their navigation state in the same location as other applications’ state.Think twice before you consider doing this, but there’s a very good chance you don’t need to!. Storing React Navigation State in your own Redux store can be difficult if you don’t know what to do.

If the only reason you are doing this is to be able to perform navigation operations from outside the component (for example, from Redux middleware), you can learn more about thisDo not use Navigation prop for navigationThe information.

React Navigation will not be specifically compatible with Redux in the next release, it can be used, but it needs to be fixed.

Well, I don’t understand why the authorities want to do this, probably to reduce maintenance costs, but it is definitely not a wise choice, and there may be surprises, for now look forward to it. I personally would not recommend using React Navigation if redux is integrated in a project.

  • react-native-router-flux

It is based on React Navigation, but provides a different API for interacting with it. There is 7600+ 🌟 on Github, which allows you to define scene transformations in a central location without passing navigator objects, and can be easily accessed anywhere in the code.

The latest beta version, version 4, introduces, among other changes, drawer support and moB-X-driven navigational state machines that separate navigational logic from the presentation layer.

  • react-native-navigation

Another popular Navigation library is React Native Navigation developed by the Wix open source team, which is close to 9000+ 🌟 on Github. Its biggest advantage is 100% Native platform Navigation with cross-platform interface coverage, with Redux support out of the box.

You need to configure this package separately for iOS and Android, which includes linking to the iOS library, updating the iOS header search path, extending SplashActivity instead of ReactActivity in Android MainActivity, and several other steps detailed in the documentation. When you’re done, you just need to register the screens of all the applications and start the application.

At present, official documents also put forward:

Note: example redux is deprecated. Since we did not have enough time and resources to maintain both example projects, we decided to stop maintaining the redux example. This does not mean redux can’t be used with react-native-navigation (In fact, we use redux in the Wix app). For a working example project which uses redux with RNN you can refer to JuneDomingo/movieapp.

Translation:

Note: Using the example redux is not recommended. Since we did not have enough time or resources to maintain the two sample projects, we decided to stop maintaining the Redux sample. This does not mean redux cannot be used with React-native navigation (in fact, we use Redux in Wix applications). For a working example project that uses Redux with RNN, you can refer to JuneDomingo/Movieapp.

To sum up: personally speaking, fromreact navigationreact-native-navigationThe official toReduxThe attitude is totally different, at leastWixIn internal useRedux. If needed in the projectReduxMy first choice would beReact Native NavigationBecause it’s a pure native experience, and yesReduxThe support is good. If not in useReduxYou can try the first two types of navigation in the project. These two types of navigation experience are also good, very close to the native experience.

Structure analysis

This article chooses to use React-native navigation. Please refer to the official documentation for the integration and API usage of React-native navigation. If you want to know how to use Redux in React Navigation, click here or here. Here is the new file code index.js

//discard import {AppRegistry} from'react-native';
AppRegistry.registerComponent('ReduxForReactNativeDemo', () => App);
Copy the code
//new
import App from './App';
new App();
Copy the code

App.js

import React, { Component } from 'react'
import { applyMiddleware, createStore } from 'redux'
import { createLogger } from 'redux-logger'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import rootReducer from './js/reducers'
import { Navigation } from 'react-native-navigation'
import { registerScreens } from './js/components/screens'

const logger = createLogger();
const store = createStore(
    rootReducer,
    applyMiddleware(thunk, logger)
);

registerScreens(store, Provider);

export default class App extends Component {

    constructor(props){
       super(props);
       this._startApp();
    }

    _startApp = () => {
        Navigation.startTabBasedApp({
            tabs: [
                {
                    label: 'Home',
                    screen: 'ReduxForReactNativeDemo.HomeScreen',
                    icon: require('./res/img/ic_home.png'),
                    // selectedIcon: require('./img/checkmark.png'),
                    title: 'Home',
                    overrideBackPress: false,
                    navigatorStyle: {}
                },
                {
                    label: 'Posts',
                    screen: 'ReduxForReactNativeDemo.PostsScreen',
                    icon: require('./res/img/ic_news.png'),
                    // selectedIcon: require('./img/checkmark.png'),
                    title: 'Posts', navigatorStyle: {} } ] }); }}Copy the code

Compared to the last versiondemoAnd the wholeApp.jsThe file code is basically changed


Other changes

Under the Components directory, the Screens directory is newly added. Under this folder, there are interface files one by one, and each interface is composed of multiple components.

  • Group.jsrenamedHomeScreen.js.
  • newPostsDetail.js,PostsScreen.js,index.js.index.jsFile is used to register all interface files.
  • Posts.jsnewitemClick the event, click to enter the list details interface.
  • LoadPosts.js 68Line new{... this.props}, in order toPosts.jsYou can go throughthis.propsAccess to thenavigator.
  • Added in the root directoryresResources folder.

Conclusion:

This structural analysis is here, say the next three demo version coherent to do down the feeling. To be honest, I learned a lot this time. I also encountered various problems in the process of practice. I consulted a large number of resources and had many questions. I have seen a lot of strange demo writing methods, rarely see the standard project engineering structure, most of them are for the purpose of achieving the effect, and can not use this project structure in the actual project, I introduced at the beginning of my article why I spend the time and energy to write this technical article. I will apply this engineering structure to future projects that integrate Redux. Finding a good learning material is really not easy, if you also feel good, might as well light up ❤️, let more people find it.


eggs

Attached demo, welcome ❤️⭐️👏 to point out mistakes or release their own opinions to explore, mutual encouragement. 🤝

Pay attention to

If you clone the latest version of the demo and run it with git tag, you can see that the demo has three tags. If you switch to the root directory and run the git tag, you can see that the demo has three tags.

Switch to the v0.1

Git checkout -b dev v0.1

Switch to the v0.2

Git checkout -b dev v0.2