Store Redux Redux Redux is a predictable state
Store Redux
Redux • Redux is a predictable state container for Java. Script apps including React Native.
Installing npm install redux@4. 0. 5 react-redux@7. 2. 1 May have to do: npm install May have to do: expo install react-native-safe-area-context (as per https: //github. com/th 3 rdwave/react-native-safe-areacontext/issues/110 )
Concepts • Reducer • Actions • Action creators • Store
Concepts App. js Screen 1 Screen 2 connect to access state dispatch action to change state Store Provides reducer functions Provides action to reducer function; reducer function changes the state
Example • Friends List Home screen Gets the number of friends from the length of the array variable current in redux store Reference: https: //www. digitalocean. com/community/tutorials/react-native-redux Friends screen When a name is clicked, removes it from the array named possible in store and adds it to the array named current in store.
Friends. Reducer. js Friends. Actions. js App. js Home. Screen. js Friends. Screen. js connect to access state dispatch action to change state Store Provides reducer functions Provides action to reducer function; reducer function changes the state
Reducer • A reducer is a pure function that takes the previous state and an action as arguments and returns a new state. • Actions are an object with a type and an optional payload function my. Reducer(previous. State, action) => { // use the action type and payload to create a new state based on // the previous state. return new. State; }
Friends. Reducer. js import { combine. Reducers } from 'redux'; const INITIAL_STATE = { current: [], This is a default object that possible: [ we’ll use to initialize the state 'Alice', 'Bob', Note that our state will contain 'Sammy', 2 arrays. The array current is initialized to empty, the array ], possible has string names. };
Friends. Reducer. js A reducer is a named function There is a default parameter; the initial state that we defined on the previous slide. const friends. Reducer = (state = INITIAL_STATE, action) => { // And put friend in friends. current switch (action. type) { current. push(added. Friend); Add the new friend to the current array. case 'ADD_FRIEND': // Finally, update the redux state const new. State = { current, possible }; // Pulls current and possible out of previous state return new. State; Create and return // We do not want to alter state directly in case default: the new state // another action is altering it at the same time return state const { } current, }; The payload of our action object possible, has the index of the new friend export default combine. Reducers({ } = state; friends: friends. Reducer // Pull friend out of friends. possible }); // Note that action. payload === friend. Index const added. Friend = possible. splice(action. payload, 1); The javascript splice function will delete the item at the index of its first parameter and return its value
Actions • Actions are plain Java. Script objects • they represent payloads of information that send data from your application to your store. • Actions have a type and an optional payload. { } type: 'ADD_TODO’, payload: { task, completed: false } • The type is used by the reducer function to determine how to change state • The payload is the new values in the state
Action Creator • Actions are often dispatched using an action creator. • An action creator is a function that returns an action object. • Action creators can seem like a superfluous step, but they make things more portable and easy to test. • The action object returned from an action creator is sent to all of the different reducers in the app.
Friends. Actions. js We’ll call this function and pass the index in the possible array of the chosen friend. export const add. Friend = friends. Index => ( { We only have one type: 'ADD_FRIEND', action creator and it just provides one payload: friends. Index, action: ’ADD_FRIEND’ } The payload will be the index in ); the possible array of the chosen friend. This function creates and returns an object
Store • In Redux, the store is where all your variables are actually kept • reducers update the store using the actions that they’re passed. • There is only a single store in a Redux application.
App. js import 'react-native-gesture-handler'; import React from 'react'; import { Provider } from 'react-redux'; import { create. Store } from 'redux'; import { Style. Sheet } from 'react-native'; import { Navigation. Container } from '@react-navigation/native'; import { create. Stack. Navigator } from '@react-navigation/stack'; import friends. Reducer from '. /Friends. Reducer'; import Home. Screen from '. /Home. Screen'; import Friends. Screen from '. /Friends. Screen';
App. js Create the store and pass it our reducer from the file Friend. Reducer. js, i. e. , the function my. Reducer const store = create. Store(friends. Reducer); <Stack. Screen const Stack = create. Stack. Navigator(); name="Friends" component={Friends. Screen} function App() { //. . . return ( /> Must wrap our navigation container in the Provider container given by redux </Stack. Navigator> </Navigation. Container> </Provider> <Provider store={store}> <Navigation. Container> ) } <Stack. Navigator> <Stack. Screen name="Home" component={Home. Screen} /> export default App;
Using Redux to access state • Create a function named map. State. To. Props • In this function use destructuring to get the object from the redux state that you want to use • Use the connect function from ‘react-redux’ to send the object as a prop to a screen
Home. Screen. js The friends array from the store is passed in props const styles = Style. Sheet. create({ import React from 'react'; container: { import { connect } from 'react-redux'; flex: 1, import { Style. Sheet, Text, View, Button } from 'react-native'; background. Color: '#fff', function Home. Screen(props) { align. Items: 'center', return ( justify. Content: 'center', }, <View style={styles. container}> }); <Text>You have {props. friends. current. length} friends. </Text> const map. State. To. Props = (state) => { <Button const { friends } = state title="Add some friends" on. Press={() => props. navigation. navigate('Friends’)} return { friends } }; /> </View> ); } export default connect(map. State. To. Props)(Home. Screen); Make the store object into a prop called friends
Using Redux to update state 1. Create a reducer function to manipulate your store 2. Create a store, passing your reducer 3. In the app where you want to change state, create an action object. 4. Then dispatch the action object to the store 5. The store will call your reducer function which will look at the type of the action and will modify the state appropriately. 6. The reducer will return the newly modified state object.
Calling the store We dispatch actions in our app using the store’s dispatch method like so: store. dispatch(add. Todo({ task: '�� Read about Redux'})); store. dispatch(add. Todo({ task: '�� Think about meaning of life' })); //. . .
Friends. Screen. js import { connect } from 'react-redux'; import { bind. Action. Creators } from 'redux'; import { Style. Sheet, Text, View, Button } from 'react-native'; import { add. Friend } from '. /Friends. Actions';
Friends. Screen. js function Friends. Screen(props) { return ( <View style={styles. container}> <Text>Add friends here!</Text> Use map on the friends array from store to create a separate button for each friend { props. friends. possible. map((friend, index) => ( <Button key={ friend } title={ `Add ${ friend }` } on. Press={() => props. add. Friend(index) } /> )) } When the button is clicked, we dispatch to the store using the function add. Friend later from the file Friends. Action. js. add. Friend is bound to the props later in this file
Friends. Screen. js The end of the screen code <Button Navigate to the Home screen title="Back to home" on. Press={() => props. navigation. navigate('Home') } /> </View> ); }
Friends. Screen. js const map. State. To. Props = (state) => { const { friends } = state return { friends } }; const map. Dispatch. To. Props = dispatch => ( bind. Action. Creators({ add. Friend, }, dispatch) ); This is the function that we use to pass the friends array via props. Same as in Home. Screen. js This function will bind the function add. Friend to the dispatch function of the store We imported the add. Friend function from the file Friends. Actions. js export default connect(map. State. To. Props, map. Dispatch. To. Props)(Friends. Screen); We must bind both of these functions to the props of the Friends. Screen
Friends. Screen. js const styles = Style. Sheet. create({ container: { flex: 1, background. Color: '#fff', align. Items: 'center', justify. Content: 'center', }, });
Setting up Friends. Reducer. js App. js Home. Screen Friends. Screen connect(map. State. To. Props)(Home. Screen) Friends. Actions. js connect(map. State. To. Props, map. Dispatch. To. Props)(Friends. Screen) Store const store = create. Store(friends. Reducer);
Using store Friends. Reducer. js App. js Home. Screen Friends. Screen props. friends. current. length Friends. Actions. js props. add. Friend(index) // dispatches the Action created by // add. Friend to the store Store friends. Reducer(state, action)
The 4 Main Steps of the Data Lifecycle in Redux 1. An event inside your app triggers a call to store. dispatch(action. Creator(payload)). 2. The Redux store calls the root reducer with the current state and the action. Payload is just the values to change
The 4 Main Steps of the Data Lifecycle in Redux 3. The root reducer combines the output of multiple reducers into a single state tree. export default const current. Task(state = {}, action){ // deal with this piece of state return new. State; }; export default const todos(state = [], action){ // deal with this piece of state return new. State; }; export default const todo. App = combine. Reducers({ todos, current. Task, });
The 4 Main Steps of the Data Lifecycle in Redux 4. When an action is emitted redux will call both reducers and combine both sets of results into a single state tree: return { todos: next. Todos, current. Task: next. Current. Task, };
- Slides: 30