Redux для реагирования на нативное руководство

внешний интерфейс React.js React Native Redux

предисловие

Если вы хотите увидеть теоретическую детскую обувь, нажмите здесьредукционная китайская документацияилиредукс официальная документация, в этой статье не будут слишком уж преднамеренно вводить крупномасштабные теории, в этой статье не проводится сравнение фреймворков, только для тех, кто хочет научитьсяreduxДетская обувь предоставляет содержательные, эффективные и простые для понимания справочные ресурсы для обучения, чтобы поделиться тем, что вы приобрели в процессе обучения. Статья будет длиннее после обновления, пожалуйста, наберитесь терпения, чтобы прочитать и понять, и внимательно попробовать. незнакомыйreduxНе беда, вы можете следовать идеям статьи и совместить триdemoПосле стука, я считаю, вы получите много пользы. (В конце текста пасхалки).

Обновленный контент

  • reduxБазовое использование (с демонстрацией)
  • redux MiddlewareИспользование (с демонстрацией)
  • reduxинтегрированныйnavigation(с демо)

redux 基本使用
подражать официальномуTodosдемоreact nativeВерсия.

redux Middleware使用
подражать официальномуasyncдемоreact nativeВерсия.

集成react-native-navigation后ios演示图
集成react-native-navigation后android演示图

интегрированныйreact-native-navigationпоставить первые дваdomoвсесторонний.

Быть обновленным

  • продолжение следует......

Почему я хочу написать это демо

К некоторым детской обуви могут возникнуть вопросы

Q: Официальный неTodosдемо? Зачем писать это демо?

О: Все официальные демоверсииreact, скорее, чемreact nativeиз. Я также нашел много о введенииredux, но я обнаружил, что информация, которую я нашел, была либо слишком простой, либо введение не было исчерпывающим, предоставленная демонстрационная загрузка была непригодной для использования и т. д., что заставило меня испытать желание построить колесо самостоятельно, и этоdemoне только оreduxОснова-то, но через три комплектаdemoПрактикуйте связную графику и текст, чтобы читатели могли лучше понять, и будут обновлены в будущем.reduxВ процессе, я надеюсь, все будут поощрять и поддерживать.

Спецификация кода, принятая демо

Обычно большой проект требует участия многих разработчиков на более позднем этапе.Если каждый разработчик использует свой собственный набор спецификаций кода, последствия этого таковы: последующая работа по управлению кодом принесет много проблем и потерь. времени на рефакторинг, а также новичкам потребуется больше времени, чтобы понять код при чтении кода, и других легко завести в канаву, поэтому крупномасштабный проект должен соблюдать некоторые спецификации при изначальном построении архитектуры.

Итак, как мы можем набирать чистый и элегантный код? Как мы можем проверить качество нашего кода? Я настоятельно рекомендую соблюдать здесьairbnb/javascriptСпецификация и использованиеeslintдля проверки качества кода вашего собственного кода (соответствует ли он спецификации), так как они были одобрены многими компаниями и разработчиками. (Здесь слишком много предисловияairbnb eslint, в этой статье только идеи, хочу узнать больше и поискать самостоятельно)

Прежде чем использовать спецификацию кода, мы, возможно, много лет писали код в своем стиле, и вдруг может быть очень неудобно адаптироваться к этой спецификации. это после долгого времени У кого нет процесса Процесс болезненный, но после боли он принесет вам качественную сублимацию, и вы сможете потихоньку его осмыслить и пережить на себе. Хорошие вещи будут приняты миром, а плохие со временем будут заменены, поэтому, как квалифицированный программист (особенно фронтенд-программист), вы должны принять изменения, потому что они сделают вас лучше, чтобы вас признали публикой, если вы не хотите сделать себя лучше.

Что может сделать для нас редукс

Две диаграммы показывают:

未使用redux的大型react native项目
使用redux后的大型react native项目

редукс-функции

  • Единый источник достоверной информации: для всего приложенияstateхранится в дереве объектов, и это дерево объектов существует только в одномstore середина.

  • Состояние доступно только для чтения: единственный способ изменить состояние — запуститьaction, действие — это обычный объект, используемый для описания произошедшего события.

  • Используйте чистые функции для выполнения модификаций: чтобы описать, как действия изменяют дерево состояний, вам нужно написатьreducers.

  • Предсказуемость: все действия пользователей определяются вами заранее.

  • Единое управление состоянием: все состояния распределяются и управляются в хранилище.

Какие разработчики и проекты подходят для редукса

здесь только дляreact nativeДля развития:

  • Новичок: только началоreact nativeЯ не рекомендую его использовать, потому что вы еще не знаете, как его использовать, рекомендуется сначала достичь среднего уровня.

  • Промежуточный: использоватьreact nativeсделать более одного уже перечисленного不复杂Приложенияredux, либо не используется, так как его использование не позволяет быстро итеративно разрабатывать на ранней стадии, и использовать его в таком проектеreduxподобно大炮打蚊子, побочные эффекты велики. Но вы можете сначала понять его и открыть для себя его преимущества. Это своего рода относительно простое приложение: когда пользователь инициирует действие (программе нужноsetState({xxx:xxx})), когда поток состояния приложения выглядит следующим образом:

    简单的状态流程

  • Дополнительно: использоватьreact nativeсделать более одного уже перечисленного复杂приложений (с обменом мгновенными сообщениями, сложной компоновкой интерфейса, слишком большим количеством уровней вложенности компонентов и т. д.) и такими сложными приложениями: когда пользователь инициирует действие (программа требуетsetState({xxx:xxx})), когда поток состояния приложения выглядит следующим образом:

    复杂的状态流程

Последствия этого состояния анализируются в двух аспектах:

  • Производительность: избыточная передача состояния между родительским и дочерним компонентами приводит к трате драгоценных ресурсов памяти, и в то же время скорость рендеринга интерфейса будет ниже, а естественный пользовательский опыт будет хуже.
  • Управление состоянием: когда программа продолжает повторяться, а макет интерфейса становится все более и более сложным, она неизбежно производит многоstateгосударство, как вы эффективно управляете этими состояниями? Что заставляет пользовательский интерфейс отображаться несколько раз? Какой шаг вызывает изменение компонентов пользовательского интерфейса? без использованияreduxВы, возможно, обнаружили ранее, что можете использоватьshouldComponentUpdateЧтобы уменьшить ненужный рендеринг в подкомпонентах, но ведь это не может решить сложную проблему управления состоянием. когда вы используетеreduxПосле этого сложный поток состояния приложения выглядит так:
    使用redux后
    Прочитав вышеприведенные картинки и тексты, у вас появилось интуитивное понимание, какие проекты подходят для редукса?Спасибо@justjavacПоддержка анимации предоставлена ​​статьей.

Redux для реагирования на собственную рабочую логическую диаграмму

благодарный@студия черный лесНаглядная логическая схема предоставлена ​​автором

清晰逻辑图

Анализ инженерной структуры Redux

Я внес некоторые изменения в официальную демо-часть локации, смотрите разбор кода:

image.png

Разделение труда

  • js/actionsЧто делает содержимое этой папки: определяет поведение пользователя.
  • js/reducersЧто делает содержимое этой папки: реагировать на поведение пользователя, возвращать измененное состояние и отправлять его вstore.
  • js/componentsЧто делает содержимое этой папки: пользовательские компоненты.
  • js/containersЧто делает содержимое этой папки: поставитьcomponentsКомпоненты в папке, связанные с изменением состояния, инкапсулируются во второй раз.
  • App.jsВходной файл (хранилище находится здесь), почему я должен определять хранилище здесь? потому что он уникален и должен использоватьсяreact-reduxкоторый предоставилProviderМожно использовать другие компоненты компонента, обертывающего запись.reduxсерединаstoreэффективный.
  • global.jsХраните глобально определенные переменные, константы, методы и т. д.

На что обратить внимание

  • в проектеreduxизstoreуникален и не может использоваться в несколькихstore.
  • ДержатьreducerЧистота очень важна. никогда вreducerВыполните эти операции в:
  • Изменить входящие параметры;
  • Выполнение операций с побочными эффектами, таких какAPIПрыжок запроса и маршрутизации;
  • вызвать нечистую функцию, напримерDate.now()илиMath.random();
  • Использование оператора распространения объекта...заменятьObject.assign()является лучшим решением.
  • Первая буква имени компонента должна быть заглавной, т.е.componentsа такжеcontainersПервая буква файлов в папке должна быть заглавной.
  • должно быть сведено к минимумуactionДанные в (могут передавать отдельные данные, но не объект, могут передавать объект, но не массив)
//good
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}
//best
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return { ...state, visibilityFilter: action.filter }
    default:
      return state
  }
}

Подробный код

js/actions/types.js

//添加列表数据
export const ADD_TODO = 'ADD_TODO';
//筛选
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
//文字添加/取消中划线
export const TOGGLE_TODO = 'TOGGLE_TODO';

выпускать:

определение действия

Почему я ставлю пользовательскийaction(поведения) определения извлекаются отдельно, чтобы написать одинtype.js?

  • Удобное управление статусами.
  • возможность повторного использования.

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
});

выпускать:

Функция создания действия

ActionЧтобы создать функцию, нужно сгенерироватьactionМетоды. "action" а также "action 创建函数Эти два понятия легко смешиваются, и лучше всего различать их при употреблении.

существуетReduxсерединаactionСоздание функции просто возвращает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:
            return state.map(todo => (todo.id === id) ? {...todo, completed: !todo.completed} : todo);
        default:
            return state;
    }
};

export  default  todos;

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;

выпускать:

reducerэто чистая функция, которая принимает старыйstateа такжеaction, вернуть новыйstate(Вышеуказанные два файла могут просматривать дваreducer).

Уведомление:

  • ReduxПри первом исполненииstateдляundefined, вам нужно установить начальныйstate.
  • каждыйreducerОтвечает только за управление глобальнымstateчасть отвечает. каждыйreducerизstateПараметры разные, соответствующие той части, которой он управляетstateданные.

js/reducers/index.js

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

export default combineReducers({
    todos,
    visibilityFilter
})

выпускать:

combineReducers()Все, что он делает, это генерирует функцию, которая вызывает вашу сериюreducer, каждыйreducer фильтровать по их ключуstateчасть данных в, а затем эта сгенерированная функция принимает всеreducerРезультаты объединяются в один большой объект.

поверхностноcombineReducers()Эффект заключается в объединении несколькихreducerсинтезированный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>
        );
    }
}

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}
            />
        )
    }
}

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>
        );
    }
}

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>
        )
    }
}

image.png
выпускать:

Вышеупомянутые четыре файла представляют собой четыре настраиваемых компонента отображения пользовательского интерфейса, эти компоненты определяют только внешний вид и не заботятся об источнике данных и способах изменения. Рендеринг всего, что передается. Если поставить код изReduxПри переходе на другие архитектуры эти компоненты можно использовать без каких-либо изменений. они не зависят отRedux.


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)

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)

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:
            return todos.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)

выпускать:

Вышеупомянутые три являются компонентами-контейнерами, которые используются для подключения компонентов дисплея кRedux. Вкратце: просто запомните одно предложение: компоненты представления пользовательского интерфейса отвечают за представление пользовательского интерфейса, а компоненты-контейнеры отвечают за управление данными и логикой.Иногда трудно сказать, следует ли вам использовать компонент контейнера или компонент представления. Как этот небольшой компонент:

  • AddTodo.jsСодержит кнопку «Добавить» и поле ввода

Технически возможно разделить его на два компонента, но, во-первых, делать это немного рано. Можно смешивать контейнеры и презентации в нескольких очень маленьких компонентах. Когда бизнес становится сложным, становится очевидным, как его разделить. Так что пока используйте гибрид.

использовано вышеreact-reduxизconnect()метод для связывания компонента представления с компонентом контейнера.Этот метод оптимизирован по производительности, чтобы избежать большого количества ненужного дублирования рендеринга. (Таким образом, вам не нужно вручную реализовывать его для повышения производительности.Реагировать на предложения по оптимизации производительности середина shouldComponentUpdateметод. )

использоватьconnect()Прежде необходимо определитьmapStateToPropsЭта функция указывает, как преобразовать текущийRedux store stateсопоставляется с компонентом презентацииpropsсередина. Например,VisibleTodoListнужно рассчитатьTodoListсерединаtodos, поэтому определите в соответствии сstate.visibilityFilterфильтроватьstate.todosметод, а вmapStateToPropsиспользуется в.

кроме чтенияstate, компоненты контейнера также могут быть распределеныaction. Аналогичным образом можно определитьmapDispatchToProps()метод полученияdispatch()метод и возвращает метод обратного вызова, который, как ожидается, будет внедрен в свойства компонента презентации. Например, мы хотимVisibleTodoList К TodoListВнедрить компонент под названиемonTodoClickРеквизит, также надеемсяonTodoClickможет распространятьTOGGLE_TODO этоaction. Наконец, используйтеconnect()СоздайтеVisibleTodoListи передать эти две функции.


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>
        );
    }
}

выпускать:

Group.jsОн заключается в том, чтобы объединить все связанные компоненты, чтобы сформировать законченный интерфейс.


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>
        );
    }
}

выпускать:

Входной файл входящийStore

  • Создайтеstoreвходящийreducers.
  • использоватьProviderупаковка компонентовGroupкомпоненты,storeперешел в собственностьProvider.

На этом анализ кода завершен. Это письмо заканчивается здесь. Я считаю, что если вы внимательно прочитаете его, вы в какой-то степени что-то приобретете.demoЕсли вы плохо это понимаете, то следуйте идее анализа кода, чтобы набрать код еще несколько раз, и тогда вы поймете Я буду продолжать обновлять незаконченный контент, когда у меня будет время.

〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️

⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️ Великолепная разделительная линия ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️

〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️

Прошло несколько дней с момента последнего обновления, и сегодняшнее обновление:Middleware(промежуточное ПО).

Роль ПО промежуточного слоя

MiddlewareвActionsа такжеDispatcherВстроенные между ними инструменты существуют для решения определенных задач и повышения эффективности нашей разработки. Вот три часто используемых промежуточного программного обеспечения:

  • redux-thunkПромежуточное ПО: требуется для асинхронных операций в проекте (например: запрос данных сервера, локального хранилища и т. д.).
  • redux-actionsПромежуточное ПО: помогает обрабатывать и создавать действияactions(Эта статья не представляет его, и его можно использовать для создания последующих проектов после сложных проектов).
  • redux-loggerПромежуточное ПО: используется для печатиactionжурнал. включиreact nativeВ режиме удаленной отладки вы можете увидеть изменение состояния печати на консоли, запустив демонстрацию.
    状态日志

Схематическая диаграмма после добавления промежуточного ПО выглядит следующим образом:

加入中间件后的示意图

Подробный основной код

этот разdemoЧтобы сократить объем статьи, код будет только объяснен.Middlewareчасть, так сказатьdemoв серединеreducers,components,containersНовые добавленные файлы не будут слишком подробно объясняться.Если вы не понимаете, вы можете вернуться и снова проанализировать содержимое первого обновления.

actions/types.jsДобавьте следующий код

//请求帖子列表
export const REQUEST_POSTS = 'REQUEST_POSTS';
//帖子返回数据
export const RECEIVE_POSTS = 'RECEIVE_POSTS';
//切换数据源
export const SELECT_SUBREDDIT = 'SELECT_SUBREDDIT';
//使缓存过期失效
export const INVALIDATE_SUBREDDIT = 'INVALIDATE_SUBREDDIT';

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 发起请求
    dispatch(requestPosts(subreddit));
    return fetch(`http://localhost:8081/data/${subreddit}.json`)
        .then(response => response.json())
        .then(json => {
            setTimeout(()=>{
                //使用 API 请求结果来更新应用的 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))
    }
};

выпускать

Главное, на что следует обратить внимание выше, это то, что

  • fetchPostsвозвращает функцию, а обычныйAction 创建函数Возвращает объект по умолчанию.
  • Параметры возвращаемой функции:dispatchа такжеgetStateэти двоеReduxметод, обычныйAction 创建函数ПараметрыActionСодержание.
  • В возвращаемой функции сначала введитеAction: dispatch(requestPosts(subreddit)), указывая на то, что операция начинается.
  • После завершения асинхронной операции выполните еще однуAction: receivePosts(subreddit, json), означающий окончание операции.

Объяснение источника данных в демо:

Я собирался использовать официальныйreddit demoAPI, и, наконец, нашел официальный данныйdemoДанные запроса сообщат об ошибке, поэтому локальные данные json используются для имитации процесса загрузки данных из сетевого API с задержкой в ​​две секунды.

官方提供的redditAPI无法使用


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>
        );
    }
}

выпускать

по сравнению с предыдущимdemoизApp.js,существуетcreateStoreПри изменении параметров появляется еще одинapplyMiddleware(thunk, logger)Параметры промежуточного ПО. Нетрудно увидеть детскую обувь, которая понимает содержание первого обновления,ActionКstore.dispatchметод отправлен. а такжеstore.dispatchВ обычных условиях параметры могут быть только объектами, а не функциями. Чтобы решить эту проблему, нам нужно использовать промежуточное ПО.redux-thunkМодернизацияstore.dispatch,Сделатьstore.dispatchМожет принимать функции в качестве параметров.

Уведомление

Некоторое промежуточное программное обеспечение имеет требования к порядку, проверьте документацию перед использованием. Например, логгер должен стоять в конце, иначе вывод будет неверным.


Это конец этого письма.

〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️

⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️ Великолепная разделительная линия ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️

〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️

Затем обновите информацию об интеграцииnavigationинтеграция, если вы использовали более старую версиюreact nativeзнаю, что вreact-navigationДо подъема большинство разработчиков использовали официально предоставленныйNavigator,доreact native v0.44.3Объявлено заброшенным при запускеNavigator.

image.png
Потому что я использовал его только в предыдущих проектахNavigatorилиreact-navigation, поэтому я не знаю, сколько подобных навигационных решений есть на рынке, но в этот раз, в период перерыва в проекте, я глубже разобрался с тремя самыми популярными навигаторами на рынке:

Это официально рекомендуется вgithubуже на1.35W+🌟, авторReact NativeСообщество поддерживается, на данный момент это самое популярноеReact NativeНавигационная библиотека. он полностью используетJavaScriptписать вместо использования родногоAPI, который воссоздает некоторые подмножества. Эта опция позволяет пользователям настраивать любую часть навигационного опыта, не изучаяiOSилиAndroidЛогика навигации. потому чтоReact Navigation的Большая часть логики находится вJavaScriptвместо запуска в родном, так что любая блокировкаJavaScriptСитуация с потоком приведет к появлению задержки. Также объяснитеreact navigationВерсия v1 сильно отличается от версии v2.Если вы хотите узнать о детской обуви, вы можете прочитать эту статью, которую я написал ранее [Реагировать на нативную мощную навигацию V2.0+ ](woo woo Краткое описание.com/fear/05 возражение 0 о 9 неплохо…).

В настоящее время в официальных документах четко указано:

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.

переводить:

Предупреждение: в следующей большой версии React Navigation, которая выйдет осенью 2018 года, мы больше не будем предоставлять информацию о том, как интегрировать Redux, и ее поддержка может быть прекращена. Проблемы с Redux, опубликованные в системе отслеживания проблем React Navigation, также будут немедленно закрыты. Интеграция Redux может продолжать работать, но не будет тестироваться или учитываться при принятии каких-либо проектных решений для библиотеки.

Некоторым людям нравится хранить свое состояние навигации в том же месте, что и остальную часть состояния приложения. Подумайте дважды, прежде чем решиться на это, но есть очень большая вероятность, что вам не придется этого делать!. Сохранение состояния React Navigation в вашем собственном магазине Redux может быть затруднено, если вы не знаете, что делаете.

Если ваша единственная причина сделать это — иметь возможность выполнять действия навигации извне компонента (например, из промежуточного программного обеспечения Redux), вы можете узнать больше оНавигация без навигационной опорыИнформация.

В переводе на простой язык:React NavigationСовместимость больше не будет преднамеренно учитываться в следующей версии.Redux, его можно использовать, но есть проблема, которая должна решаться сама собой.

Эй, я не понимаю, почему чиновник делает это, может быть, это для снижения затрат на обслуживание, но это, несомненно, неразумный выбор, и могут быть сюрпризы, так что давайте пока с нетерпением ждем этого. Если проект объединяетreduxЯ лично не рекомендую использоватьReact Navigation.

это основано наReact Navigation, но обеспечивает другоеAPI. существуетgithubуже на7600+🌟, который позволяет вам определять переходы сцен в одном центральном месте без передачи объекта навигатора и легко доступен в любом месте вашего кода.

Последняя бета-версия 4, среди прочих изменений, представляет поддержку ящиков и конечный автомат навигации на основе Mob-X, который отделяет логику навигации от уровня представления.

Другая популярная навигационная библиотека предоставляетсяWixРазработано командой с открытым исходным кодомReact Native Navigation,существуетgithubблизко к9000+🌟, его самым большим преимуществом является 100% нативная навигация по платформам с наложением межплатформенного интерфейса, с готовымиReduxслужба поддержки.

тебе следуетiOSа такжеAndroidНастройте этот пакет индивидуально, включая ссылкуiOSбиблиотека, обновлениеiOSпуть поиска заголовка, вAndroid MainActivityсредняя протяженностьSplashActivityвместоReactActivityи несколько других шагов, подробно описанных в документации. После этого вам просто нужно зарегистрировать все экраны приложения и запустить приложение.

В текущем официальном документе также предлагается:

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.

переводить:

Примечание. Пример избыточности устарел. Поскольку у нас недостаточно времени и ресурсов для поддержки этих двух проектов-примеров, мы решили прекратить поддержку избыточных примеров. Это не означает, что redux нельзя использовать с react-native-navigation (на самом деле мы используем redux в приложении Wix). Для рабочего примера проекта, использующего редукцию с RNN, вы можете обратиться к JuneDomingo/movieapp.

Подводя итог: лично отreact navigationа такжеreact-native-navigationофициальная параReduxотношение совершенно другое, по крайней мереWixиспользуется внутриRedux. Если в проекте необходимо использоватьRedux, мой первый выбор был быReact Native Navigation, потому что это чисто родной опыт, иReduxПоддержка хорошая. Если не использоватьReduxВ проекте вы можете попробовать первые два вида навигации, эти два вида навигации также хороши, очень близки к родному опыту.

Структурный анализ

Использование выбора навигации по этой статьеreact-native-navigationreact-native-navigationИнформацию об интеграции и использовании API см.официальная документация, если вы хотите узнатьReact Navigationиспользуется вredux кликните сюдаилиздесь, следующий код файла изменен и добавлен в этом обновлении index.js

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

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: {}

                }
            ]
        });
    }

}

по сравнению с предыдущей версиейdemo,весьApp.jsКод файла в основном изменен


другие изменения

существуетcomponentsДобавить в каталогscreensкаталог, который содержит файлы интерфейса один за другим, и каждый интерфейс состоит из нескольких компонентов.

  • Group.jsпереименовать вHomeScreen.js.
  • новыйPostsDetail.js,PostsScreen.js,index.js,index.jsРоль файла заключается в регистрации всех файлов интерфейса.
  • Posts.jsновыйitemНажмите на событие, чтобы войти в интерфейс сведений о списке.
  • LoadPosts.js 68новая линия{...this.props}, чтобыPosts.jsвнутри черезthis.propsполучатьnavigator.
  • Добавить в корневой каталогresпапка ресурсов.

Суммировать:

На этом структурный анализ заканчивается, давайте поговорим о следующих трех.demoТакое ощущение, что это стабильная версия. Честно говоря, за это время я многому научился, а также столкнулся с различными проблемами в процессе практики, перечитал большое количество ресурсов и задал много вопросов, в итоге решал их один за другим, и ответы потихоньку всплывали. видел многоdemoСуществуют всевозможные странные способы написания, и редко можно увидеть стандартную инженерную структуру проекта.Большинство из них предназначены для достижения эффектов, и такая структура проекта не может быть использована в реальных проектах. моя статья, я рассказал мне, почему я потратил время и силы на написание этой технической статьи. Я буду применять эту инженерную структуру для будущей интеграцииreduxв проекте. На самом деле найти хороший учебный материал непросто. Если вы считаете, что он хорош, вы можете зажечь ❤️, чтобы больше людей могли его открыть для себя.


пасхальные яйца

прикреплятьdemo, добро пожаловать ❤️⭐️👏, чтобы указать на ошибки или опубликовать свое собственное мнение, чтобы обсудить и поддержать друг друга. 🤝

Уведомление

непосредственныйcloneЕсли вы запустите его, вы увидите содержимое последнего (v3) обновления по умолчанию.demo, воплощать в жизньgit tagЕсть три демонстрации, которые можно увидетьtag, если перейти на два предыдущих обновленияdemoСодержание: Выполнить в корневом каталоге:

перейти на версию 0.1

git checkout -b dev v0.1

перейти на версию 0.2

git checkout -b dev v0.2