Philip7899
Philip7899

Reputation: 4677

React-Native Redux works in 1st reducer but not 2nd

I am new to react native and redux.

In this file friends.js, I have already made it so that the app adds a friend when someone taps the "Add Friend" button. I am now also trying to make a form that adds a new name to a list of names. Here is the form:

import React from 'react';
import { StyleSheet, Text, View, Button, TextInput, KeyboardAvoidingView } from 'react-native';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import {addFriend} from './FriendActions';
import {addFriendFromForm} from './FriendActions';

class Friends extends React.Component {
    constructor(){
     super();
     this.formFieldValue = "";
    }
  render() {
    return (
      <KeyboardAvoidingView behavior="padding" enabled>
        <Text>Add friends here!</Text>
        {this.props.friends.possible.map((friend,index) => (
                <Button 
                    title={`Add ${friend}`}
                    key={friend}
                    onPress = { () =>
                        this.props.addFriend(index)
                    }
                / >
            )
        )}
        <Button 
            title="Back to Home" 
            onPress={() => this.props.navigation.navigate('Home')} 
        />
        <TextInput 
            style={{height: 40, width: 200}}
            placeholder="Type in a friend's name"
            onChangeText={(text) => {
                    this.formFieldValue = text; 
                    console.log(this.formFieldValue);
                }
            }
        />
        <Button
            title="Add Friend From Form"
            onPress={() => this.props.addFriendFromForm(this.formFieldValue)}
        / >

      </KeyboardAvoidingView>
    );
  }
}

const mapStateToProps = (state) => {
  const  friends  = state;
  console.log("friends", JSON.stringify(friends));
  return  friends 
};

const mapDispatchToProps = dispatch => (
    bindActionCreators({
        addFriend,
        addFriendFromForm
    }, dispatch)
);

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

Here is the action that the form triggers:

export const addFriend = friendIndex => ({
    type: 'ADD_FRIEND',
    payload: friendIndex
})

export const addFriendFromForm = friendNameFromForm => ({
    type: 'ADD_FRIEND',
    payload: friendNameFromForm
})

And here is the reducer that calls the actions . (WHERE I THINK THE PROBLEM IS):

import {combineReducers} from 'redux';
const INITIAL_STATE = {
    current: [],
    possible: [
        'Allie',
        'Gator',
        'Lizzie',
        'Reptar'
    ]
};
const friendReducer = (state = INITIAL_STATE, action) => {
    switch(action.type){
        case 'ADD_FRIEND':
            const {
                current,
                possible
            } = state;
            const addedFriend = possible.splice(action.payload, 1);
            current.push(addedFriend);
            const newState = {current, possible};
            return newState;
        case 'ADD_FRIEND_FROM_FORM':
            const {
                currents,
                possibles
            } = state;
            currents.push(action.payload);
            const newState2 = {current: currents, possible: possibles};
            return newState2;
        default:
            return state;
    }
};

export default combineReducers({
    friends: friendReducer
});

As I mentioned, pressing the button to automatically add a name from the initial state works. However, when adding a name through the form, it seems that the form will just add allie to possible friends instead of the name typed into the form because the console.log in friends.js shows this: friends {"friends":{"current":[["Allie"]],"possible":["Gator","Lizzie","Reptar"]}}.

  1. How do I get the form to work?
  2. I used this.formFieldValue in friends.js as it seems like overkill to change the state whenever the form field text changes when we really only need it when the submit button is pressed. Is this the proper way to go about sending the form data to the action?

While it may seem liike I'm asking 2 questions, I'm pretty sure it's one answer that will tie them both togethor. Thanks!

Upvotes: 1

Views: 29

Answers (1)

Clarity
Clarity

Reputation: 10873

The issue might be that you're directly mutating the state with push, try using array spread instead:

const friendReducer = (state = INITIAL_STATE, action) => {
    switch(action.type){
        case 'ADD_FRIEND':
            const {
                current,
                possible
            } = state;
            const addedFriend = possible.splice(action.payload, 1);
            current.push(addedFriend);
            const newState = {current, possible};
            return newState;
        case 'ADD_FRIEND_FROM_FORM':
            return {...state, current: [...state.current, action.payload]}
        default:
            return state;
    }
};

Also it's a good idea to be consistent with the property names, it seems you're using current and currents interchangeably.

Upvotes: 1

Related Questions