Reputation: 4677
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"]}}
.
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
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