在React Native應用程序中使用Redux示例

infoxiao

在React Native應用程序中使用Redux示例

這是在React Native應用程序中使用Redux示例。 我們都知道 Redux 是一個狀態管理庫,它將幫助您在一個名為的地方管理所有狀態 店鋪。 在 React Native 中集成 Redux 的幫助非常簡單 反應還原。 在這個例子中我們將看到

  1. 在 React Native 應用程序中設置 Redux 庫
  2. 在單個頁面中管理狀態
  3. 調度動作並在減速器中處理它們
  4. 使用 Redux 存儲中的不同狀態

我們請求所有剛接觸 React Native 並想要學習這個概念的讀者,請花一些時間來理解 props、state 和 Components。 一旦你對此有了清晰的認識,那麼你就可以從 Redux 開始了。 雖然使用 Redux 創建 React Native 應用程序非常簡單,但如果不理解基本概念,你會發現它有點複雜。

推薦:使用React Native應用程序在Google Drive上存儲檢索文件

什麼是 Redux?

終極版 是一個狀態管理庫,可幫助您將應用程序邏輯組織在一個地方,以便您的應用程序可以按您的預期工作。 Redux 使您的應用程序代碼非常易於理解,並且您可以管理有關應用程序狀態何時、何地、為何以及如何更新的邏輯 + 狀態。 它由以下幾個關鍵部分組成:

  • actions
  • reducers
  • store
  • dispatch
  • selector

動作和動作創建者

一個actions行動 是一個普通的 JavaScript 對象,具有類型字段和可選的有效負載。 它也可以被認為是描述已經發生的事情的事件。

export const addToBookmark = (item) => {
  return (dispatch) => {
    dispatch({
      type: 'ADD_BOOKMARK',
      payload: item,
    });
  };
};

動作創作者 只是創建和返回操作對象的函數。

reducers

reducers減速器 也是一個接收當前狀態和操作對象的函數,如果需要更新狀態並返回新狀態。 不允許減速器修改現有狀態; 相反,它複製現有狀態並更改複製的值。 換句話說,reducer 應該是一個純函數。 這是一個例子

const initialState = {
  bookmarkItems: (),
};

const reducers = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_BOOKMARK':
      return Object.assign({}, state, {
        counter: state.counter + 1,
        bookmarkItems: (...state.bookmarkItems, action.payload),
        postData: filter_records(state.postData, (
          ...state.bookmarkItems,
          action.payload,
        )),
        sort: 'NA',
      });
    .....
    .....
    .....
  }
};

store

store 是一個存儲 Redux 應用程序當前狀態的對象。 您可以通過將減速器傳遞給來創建存儲的初始狀態 createStore 功能。

import {createStore} from 'redux';
import rootReducer from './src/utils/reducers';
const store = createStore(rootReducer);

調度和選擇器

dispatch() 是 Redux 存儲方法,用於通過傳遞操作對象來更新狀態。

dispatch(addToBookmark(item))

選擇器用於從存儲中讀取數據。

這是一個流程,可以幫助您更好地理解它。

React_native_redux_flow

React Native Redux 示例描述

在此示例中,我們將創建一個簡單的書籤應用程序,它將有 2 個屏幕,一個用於列出添加的書籤,另一個用於列出帖子。 我們不會將書籤永久存儲在應用程序中,因為這只是為了理解 Redux 的概念。

每當用戶登陸書籤屏幕時,他/她都會看到添加的所有書籤(第一次什麼都沒有)。 每當用戶想要添加書籤時,他/她可以單擊書籤屏幕中的添加按鈕,並且可以看到帖子列表以在書籤中添加任何帖子。 一旦用戶點擊任何帖子,該帖子就會從帖子列表中消失並添加到書籤中,用戶可以在標題中看到添加的書籤總數。 當用戶按下後退按鈕時,他/她將看到更新的書籤列表,該列表可以根據帖子 ID 升序/降序排序。

對於帖子列表,我們有 發布數據 在商店中註明我們有書籤 書籤項目。 每當用戶登陸帖子屏幕時,我們都會調度 獲取帖子列表 函數作為一個動作,它將是一個異步函數,我們使用了react-thunk中間件。 一旦我們得到獲取的響應,我們將調度一個帶有有效負載的操作,該操作將更新我們的 發布數據 狀態這將幫助我們渲染帖子列表。

單擊任何帖子後,我們將發送 添加到書籤 帶有有效負載的操作將添加單擊的紀錄 書籤項目 並將該記錄從 發布數據。 如上所述,用戶還可以對書籤列表進行排序,這可以使用 排序書籤列表 行動。

我希望您明白我們要做什麼,所以讓我們開始使用 Redux 創建 React Native 應用程序。

製作 React Native 應用程序

React Native 入門將幫助您更多地了解如何製作 React Native 項目。 我們將使用 React Native 命令行界面來製作我們的 React Native 應用程序。

如果您之前安裝了全局的react-native-cli軟件包,請將其刪除,因為它可能會導致意外問題:

npm uninstall -g react-native-cli @react-native-community/cli

運行以下命令創建一個新的 React Native 項目

npx react-native init ProjectName

如果你想使用特定的 React Native 版本啟動一個新項目,你可以使用 –version 參數:

npx react-native init ProjectName --version X.XX.X

注意如果上述命令失敗,您可能使用的是舊版本 react-native 或者 react-native-cli 在您的電腦上全局安裝。 嘗試卸載 cli 並使用 npx 運行 cli。

這將在項目目錄中創建一個帶有名為 App.js 的索引文件的項目結構。

安裝依賴項

要安裝任何依賴項,請打開終端並使用以下命令跳轉到項目中

cd ProjectName

要在 React Native 中使用 Redux,我們需要安裝 還原 這是一個獨立的庫,可以與任何 UI 層或框架一起使用,我們還需要安裝 反應還原 這是 React 的官方 Redux UI 綁定庫。

對於這個例子,我們調用一個 API,它是一個異步操作,為此我們需要添加 redux-thunk 支持同樣的。

npm install redux react-redux redux-thunk --save

我們在此示例中使用 React Navigation,因此我們還需要安裝導航的依賴項

npm install @react-navigation/native --save

其他導航支持庫

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view --save

對於堆棧導航器

npm install @react-navigation/stack --save

此命令會將所有依賴項複製到您的 node_module 目錄中。 –save 是可選的,它只是更新 package.json 文件中的依賴項。

項目目錄/文件結構

要開始此示例,您需要創建以下目錄/文件結構。 項目將有一個 源代碼 包含我們所有代碼的目錄,src 目錄將還有兩個目錄 成分實用程序。 所有這些目錄將包含以下文件作為完整示例。

react_native_redux_exmaple_struct

你可以看到

  1. 應用程序.js 包含主導航
  2. src/BookmarkScreen.js,包含所有書籤的登陸頁面
  3. src/PostList.js, 包含用戶可以添加到書籤的帖子列表
  4. src/components/HeaderCountLabel.jsPostList 標題中的計數器標籤顯示添加的書籤數量
  5. src/components/HeaderSortLabel.js對添加的書籤進行排序
  6. src/utils/actions.js,具有所有動作函數定義
  7. src/utils/reducers.js,擁有基於動作的所有狀態管理

在 React Native 中使用 Redux 的代碼

應用程序.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
import 'react-native-gesture-handler';

import * as React from 'react';
import thunk from 'redux-thunk';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

import rootReducer from './src/utils/reducers';
import HeaderSortLabel from './src/components/HeaderSortLabel';
import HeaderCountLabel from './src/components/HeaderCountLabel';

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

import BookmarkScreen from './src/BookmarkScreen';
import PostList from './src/PostList';

const Stack = createStackNavigator();

const AppNavigator = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="BookmarkScreen"
        screenOptions={{
          headerStyle: {
            backgroundColor: '#f4511e',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}>
        <Stack.Screen
          name="BookmarkScreen"
          component={BookmarkScreen}
          options={{
            title: 'Bookmarks',
            headerRight: () => <HeaderSortLabel />,
          }}
        />
        <Stack.Screen
          name="PostList"
          component={PostList}
          options={{
            title: 'Posts',
            headerRight: () => <HeaderCountLabel />,
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

const App = () => {
  return (
    <Provider store={store}>
      <AppNavigator />
    </Provider>
  );
};

export default App;

src/BookmarkScreen.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
import React from 'react';
import {
  FlatList,
  View,
  Text,
  SafeAreaView,
  StyleSheet,
  Image,
  TouchableOpacity,
} from 'react-native';
import {connect} from 'react-redux';
import {removeFromBookmark} from './utils/actions';

const BookmarkScreen = (props) => {
  const getItem = (item) => {
    props.removeFromBookmark(item);
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.container}>
        <Text style={styles.titleStyle}>
          React Native + Redux Example
        </Text>
        <Text style={{textAlign: 'center'}}>
          Total Bookmarks: {props.counter}
        </Text>
        <FlatList
          data={props.bookmarkItems}
          ItemSeparatorComponent={
            () => <View style={styles.divider} />
          }
          renderItem={({item}) => {
            return (
              <TouchableOpacity onPress={() => getItem(item)}>
                <View style={styles.innerContainer}>
                  <Text>
                    Id: {item.id}
                    {'\n'}
                    Title: {item.title}
                    {'\n'}
                    Body : {item.body}
                  </Text>
                  <Text style={styles.itemRed}>
                    Remove from Bookmark
                  </Text>
                </View>
              </TouchableOpacity>
            );
          }}
          keyExtractor={(_item, index) => index.toString()}
        />
        <TouchableOpacity
          activeOpacity={0.7}
          onPress={() => props.navigation.navigate('PostList')}
          style={styles.touchableOpacityStyle}>
          <Image
            source={{
              uri:
                'https://raw.githubusercontent.com/AboutReact/sampleresource/master/plus_icon.png',
            }}
            style={styles.floatingButtonStyle}
          />
        </TouchableOpacity>
      </View>
      <Text
        style={{
          fontSize: 16,
          textAlign: 'center',
          color: 'grey',
        }}>
        www.aboutreact.com
      </Text>
    </SafeAreaView>
  );
};

const mapStateToProps = (state) => {
  const {counter, bookmarkItems} = state;
  return {
    counter: counter,
    bookmarkItems: bookmarkItems,
  };
};

const mapDispatchToProps = (dispatch) => ({
  removeFromBookmark: (item) => dispatch(removeFromBookmark(item)),
});

export default connect(mapStateToProps, mapDispatchToProps)(BookmarkScreen);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    padding: 10,
  },
  titleStyle: {
    fontSize: 22,
    fontWeight: 'bold',
    textAlign: 'center',
    padding: 10,
  },
  textStyle: {
    fontSize: 16,
    textAlign: 'center',
    padding: 10,
  },
  touchableOpacityStyle: {
    position: 'absolute',
    width: 50,
    height: 50,
    alignItems: 'center',
    justifyContent: 'center',
    right: 30,
    bottom: 30,
  },
  floatingButtonStyle: {
    resizeMode: 'contain',
    width: 50,
    height: 50,
  },
  innerContainer: {
    padding: 10,
  },
  itemRed: {
    color: 'red',
  },
  divider: {
    height: 0.5,
    width: '100%',
    backgroundColor: '#C8C8C8',
  },
});

src/PostList.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
import React, {useState} from 'react';
import {
  View,
  Text,
  SafeAreaView,
  StyleSheet,
  FlatList,
  TouchableOpacity,
} from 'react-native';
import {connect} from 'react-redux';
import {getPostsList, addToBookmark} from './utils/actions';

const PostList = (props) => {
  useState(() => {
    props.getPostsList();
  }, ());

  return (
    <SafeAreaView style={styles.container}>
      <View style={{flex: 1}}>
        <FlatList
          data={props.postData}
          ItemSeparatorComponent={
            () => <View style={styles.divider} />
          }
          renderItem={({item}) => {
            return (
              <TouchableOpacity
                onPress={() => {
                  props.addToBookmark(item);
                }}>
                <View style={styles.innerContainer}>
                  <Text>
                    Id: {item.id}
                    {'\n'}
                    Title: {item.title}
                    {'\n'}
                    Body : {item.body}
                  </Text>
                  <Text style={styles.itemRed}>
                    Click to Add in Bookmark
                  </Text>
                </View>
              </TouchableOpacity>
            );
          }}
          keyExtractor={(_item, index) => index.toString()}
        />
      </View>
    </SafeAreaView>
  );
};

const mapStateToProps = (state) => {
  const {postData} = state;
  return {
    postData: postData,
  };
};

const mapDispatchToProps = (dispatch) => ({
  getPostsList: () => dispatch(getPostsList()),
  addToBookmark: (item) => dispatch(addToBookmark(item)),
});

export default connect(mapStateToProps, mapDispatchToProps)(PostList);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    padding: 10,
  },
  innerContainer: {
    padding: 10,
  },
  itemRed: {
    color: 'red',
  },
  divider: {
    height: 0.5,
    width: '100%',
    backgroundColor: '#C8C8C8',
  },
});

src/components/HeaderCountLabel.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
import React from 'react';
import {Text} from 'react-native';
import {connect} from 'react-redux';

const HeaderCountLabel = (props) => {
  return (
    <Text style={{color: 'white', fontWeight: 'bold', padding: 10}}>
      Bookmarked: {props.counter}
    </Text>
  );
};

const mapStateToProps = (state) => {
  const {counter} = state;
  return {
    counter: counter,
  };
};

export default connect(mapStateToProps)(HeaderCountLabel);

src/components/HeaderSortLabel.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
import React from 'react';
import {Text} from 'react-native';
import {connect} from 'react-redux';
import {sortBookMarkList} from '../utils/actions';

const HeaderSortLabel = (props) => {
  return (
    <Text
      style={{color: 'white', fontWeight: 'bold', padding: 10}}
      onPress={() => props.sortBookMarkList()}>
      Sort: {props.sort}
    </Text>
  );
};

const mapStateToProps = (state) => {
  const {sort} = state;
  return {
    sort: sort,
  };
};

const mapDispatchToProps = (dispatch) => ({
  sortBookMarkList: () => dispatch(sortBookMarkList()),
});

export default connect(mapStateToProps, mapDispatchToProps)(HeaderSortLabel);

src/utils/actions.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
export const addToBookmark = (item) => {
  return (dispatch) => {
    dispatch({
      type: 'ADD_BOOKMARK',
      payload: item,
    });
  };
};

export const removeFromBookmark = (item) => {
  return (dispatch) => {
    dispatch({
      type: 'REMOVE_BOOKMARK',
      payload: item,
    });
  };
};

export const sortBookMarkList = () => {
  return (dispatch) => {
    dispatch({
      type: 'SORT_BOOKMARK_LIST',
    });
  };
};

export const getPostsList = () => {
  return (dispatch) => {
    fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'GET',
    })
      .then((response) => response.json())
      .then((responseJson) => {
        dispatch({
          type: 'POST_LIST_DATA',
          payload: responseJson,
        });
      })
      .catch((error) => {
        console.error(error);
      });
  };
};

src/utils/reducers.js

// Use of Redux in React Native App | React Native Redux
// https://aboutreact.com/react-native-redux/
const initialState = {
  counter: 0,
  bookmarkItems: (),
  sort: 'NA',
  postData: (),
};

const reducers = (state = initialState, action) => {
  switch (action.type) {
    case 'REMOVE_BOOKMARK':
      let newBookmarkItems =
        state.bookmarkItems.filter((bookmarkPost) => {
        return action.payload.id != bookmarkPost.id;
      });
      return Object.assign({}, state, {
        counter: state.counter - 1,
        bookmarkItems: newBookmarkItems,
      });
    case 'ADD_BOOKMARK':
      return Object.assign({}, state, {
        counter: state.counter + 1,
        bookmarkItems: (...state.bookmarkItems, action.payload),
        postData: filter_records(state.postData, (
          ...state.bookmarkItems,
          action.payload,
        )),
        sort: 'NA',
      });
    case 'SORT_BOOKMARK_LIST':
      let sortedBookMarks = state.bookmarkItems;
      let sortOrder="NA";
      if (state.sort == 'NA') {
        sortedBookMarks.sort(sort_by('id', true, parseInt));
        sortOrder="ASC";
      } else if (state.sort == 'ASC') {
        sortedBookMarks.sort(sort_by('id', false, parseInt));
        sortOrder="DESC";
      } else if (state.sort == 'DESC') {
        sortedBookMarks.sort(sort_by('id', true, parseInt));
        sortOrder="ASC";
      }
      return Object.assign({}, state, {
        sort: sortOrder,
        bookmarkItems: (...sortedBookMarks),
      });
    case 'POST_LIST_DATA':
      return Object.assign({}, state, {
        postData: filter_records(
          action.payload,
          state.bookmarkItems
        ),
      });
    default:
      return state;
  }
};

const filter_records = (mainArray, childArray) => {
  return mainArray.filter((mainElement) => {
    if (childArray.length > 0) {
      let isReturnable = true;
      childArray.forEach((childElement) => {
        if (Number(mainElement.id) === Number(childElement.id)) {
          isReturnable = false;
        }
      });
      return isReturnable;
    } else return mainElement;
  });
};

const sort_by = (field, reverse, primer) => {
  const key = primer
    ? function (x) {
        return primer(x(field));
      }
    : function (x) {
        return x(field);
      };
  reverse = !reverse ? 1 : -1;
  return function (a, b) {
    return
      (a = key(a)), (b = key(b)), reverse * ((a > b) - (b > a));
  };
};

export default reducers;

運行 React Native 應用程序

再次打開終端並使用跳轉到您的項目。

cd ProjectName

1. 啟動 Metro Bundler

首先,您需要啟動 Metro,React Native 附帶的 JavaScript 捆綁器。 要啟動 Metro 捆綁程序,請運行以下命令

npx react-native start

一旦您啟動 Metro Bundler,它將永遠在您的終端上運行,直到您將其關閉。 讓 Metro Bundler 在自己的終端中運行。 打開一個新終端並運行該應用程序。

2.啟動React Native應用程序

在 Android 虛擬設備或真實調試設備上運行項目

npx react-native run-android

或在 iOS 模擬器上運行(僅限 macOS)

npx react-native run-ios

這就是在 React Native 應用程序中使用 Redux 的方法。 Redux 是一個很有價值的工具,但只有以正確的方式使用它才有用。 Redux 可能有用的一些情況包括由許多人正在處理的代碼或包含大量應用程序狀態的應用程序。

推薦:4個不同的命令來關閉重新啟動Ubuntu Linux

MetShop为您提供可靠、独立、安全的账号合租服务,便捷订阅Netflix高级会员,油管家庭组会员,Spotify会员等多种国际流媒体会员账号。

相關文章

如何取得Windows小工具來監控硬體使用量

在Microsoft Excel中添加次坐標軸的6種方法

如何更新Windows受保護磁碟機上的BitLocker密碼

如何修復Windows 10和11中的相片檔案系統錯誤

發佈留言