diff --git a/with-redux/App.js b/with-redux/App.js new file mode 100644 index 00000000..61516c5b --- /dev/null +++ b/with-redux/App.js @@ -0,0 +1,11 @@ +import { Provider } from "react-redux"; +import { store } from "./redux/store"; +import CounterScreen from "./CounterScreen"; + +export default function App() { + return ( + + + + ); +} diff --git a/with-redux/CounterScreen.js b/with-redux/CounterScreen.js new file mode 100644 index 00000000..0b9b1d07 --- /dev/null +++ b/with-redux/CounterScreen.js @@ -0,0 +1,113 @@ +import React, { useState } from "react"; +import { + View, + Text, + TextInput, + StyleSheet, + TouchableOpacity, +} from "react-native"; +import { useDispatch, useSelector } from "react-redux"; +import { + increment, + decrement, + incrementByAmount, + decrementByAmount, +} from "./redux/slices/counterSlice"; + +const CounterComponent = () => { + const [inputValue, setInputValue] = useState(""); + const dispatch = useDispatch(); + const counter = useSelector((state) => state.counter.value); + + const handleIncrement = () => { + dispatch(incrementByAmount(Number(inputValue) || 0)); + }; + + const handleDecrement = () => { + dispatch(decrementByAmount(Number(inputValue) || 0)); + }; + + return ( + + + Expo with Redux State Management + + + Counter: {counter} + + + + dispatch(increment())} + > + Increment + + dispatch(decrement())} + > + Decrement + + + + + Increment or Decrement with Custom Values + + + + + + + Increment + + + Decrement + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + }, + buttonContainer: { + maxWidth: 200, + flexDirection: "row", + justifyContent: "space-between", + marginBottom: 15, + }, + button: { + backgroundColor: "#000000", + paddingVertical: 10, + paddingHorizontal: 20, + borderRadius: 5, + marginRight: 10, + }, + buttonText: { + color: "#ffffff", + fontSize: 16, + textAlign: "center", + }, + inputText: { + height: 40, + width: 300, + borderColor: "#000000", + borderWidth: 1, + borderRadius: 10, + paddingHorizontal: 10, + marginBottom: 20, + backgroundColor: "#fff", + }, +}); + +export default CounterComponent; diff --git a/with-redux/README.md b/with-redux/README.md new file mode 100644 index 00000000..421f2630 --- /dev/null +++ b/with-redux/README.md @@ -0,0 +1,49 @@ +# Expo with Redux Counter Example + +

+ + + Supports Expo iOS + + + + Supports Expo Android + + + + Supports Expo Web + +

+ +This project shows how to integrate **Redux** with an **Expo** app using a simple counter application where you can: + +- Increment or decrement the counter value. +- Increment or decrement the value by a custom input. + +## 🚀 How to use + +- Navigate to the project directory: + +```bash +cd with-redux +``` + +- Install Dependencies: + +```bash +npm install +# or +yarn install +``` + +Start the development server: + +```bash +npm start +# or +yarn start +``` + +## 📝 Notes + +- Learn more about [Redux](https://redux.js.org/) diff --git a/with-redux/app.json b/with-redux/app.json new file mode 100644 index 00000000..fd9aba0b --- /dev/null +++ b/with-redux/app.json @@ -0,0 +1,12 @@ +{ + "expo": { + "name": "blank", + "slug": "blank", + "version": "1.0.0", + "platforms": [ + "ios", + "android", + "web" + ] + } +} diff --git a/with-redux/babel.config.js b/with-redux/babel.config.js new file mode 100644 index 00000000..2900afe9 --- /dev/null +++ b/with-redux/babel.config.js @@ -0,0 +1,6 @@ +module.exports = function(api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + }; +}; diff --git a/with-redux/package.json b/with-redux/package.json new file mode 100644 index 00000000..f029615f --- /dev/null +++ b/with-redux/package.json @@ -0,0 +1,20 @@ +{ + "scripts": { + "start": "expo start", + "android": "expo start --android", + "ios": "expo start --ios", + "web": "expo start --web" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.5.0", + "expo": "^52.0.16", + "react": "18.3.1", + "react-dom": "18.3.1", + "react-native": "0.76.3", + "react-native-web": "~0.19.6", + "react-redux": "^9.2.0" + }, + "devDependencies": { + "@babel/core": "^7.19.3" + } +} diff --git a/with-redux/redux/slices/counterSlice.js b/with-redux/redux/slices/counterSlice.js new file mode 100644 index 00000000..e0cc1296 --- /dev/null +++ b/with-redux/redux/slices/counterSlice.js @@ -0,0 +1,24 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const counterSlice = createSlice({ + name: "counter", + initialState: { value: 0 }, + reducers: { + increment: (state) => { + state.value += 1; + }, + decrement: (state) => { + state.value -= 1; + }, + incrementByAmount: (state, action) => { + state.value += action.payload; + }, + decrementByAmount: (state, action) => { + state.value -= action.payload; + }, + }, +}); + +export const { increment, decrement, incrementByAmount, decrementByAmount } = + counterSlice.actions; +export default counterSlice.reducer; diff --git a/with-redux/redux/store.js b/with-redux/redux/store.js new file mode 100644 index 00000000..0d35146d --- /dev/null +++ b/with-redux/redux/store.js @@ -0,0 +1,8 @@ +import { configureStore } from "@reduxjs/toolkit"; +import counterReducer from "./slices/counterSlice"; + +export const store = configureStore({ + reducer: { + counter: counterReducer, + }, +});