I made a edit screen and trying to update the value of post through navigation v4 by using getParams and set setParams but when I change the old value and click save buttton to save it, it's not updating it and no error is showing either. It's still showing old values. Can someone please help me, below is my code
EditScreen.js
class EditScreen extends Component {
render() {
const { params } = this.props.navigation.state;
return (
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 100}
>
<Image
style={styles.image}
source={this.props.navigation.getParam("image")}
/>
<View style={styles.detailContainer}>
<AppTextInput
value={this.props.navigation.getParam("title")}
onChangeText={(text) =>
this.props.navigation.setParams({ title: text })
}
/>
<AppTextInput
value={this.props.navigation.getParam("des")}
onChangeText={(text) =>
this.props.navigation.setParams({ des: text })
}
/>
</View>
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit");
this.props.navigation.goBack();
}}
/>
</KeyboardAvoidingView>
Home.js
class Home extends Component {
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
onEdit = (data) => {
const newPosts = this.state.post.map((item) => {
if (item.key === data.key) return data;
else return item;
});
this.setState({ post: newPosts, editMode: false });
};
render() {
return (
<Screen style={styles.screen}>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() =>
this.props.navigation.navigate("Edit", {
image: item.image,
title: item.title,
des: item.des,
onEdit: this.onEdit,
})
}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card onPress={() => this.props.navigation.push("Details", item)}>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title} numberOfLines={1}>
{item.title}
</Text>
<Text style={styles.subTitle} numberOfLines={2}>
{item.des}
</Text>
</View>
</Card>
</>
I recommend you to keep the data in the component state:
constructor(props) {
super(props);
// get the data that you need from navigation params
const { key, title, ..} = this.props.navigation.state.params
this.state = {key, title, ..}
}
then :
<AppTextInput
value={this.state.title}
onChangeText={(text) =>
this.setState({ title: text })
}
/>
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit")(this.state);
this.props.navigation.goBack();
}}
/>
Maybe try this:
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit")(this.props.navigation.state.params);
this.props.navigation.goBack();
}}
/>
and:
this.props.navigation.navigate("Edit", {
key: item.key,
image: item.image,
title: item.title,
des: item.des,
onEdit: this.onEdit,
})
Related
Absolute react-native noob here. I am struggling with updating the 'selected item'. I'm using this as a piece of dummy data:
this.state = {
branch: '',
completedBy: '',
reportedTo: '',
branchData: {
text: 'Branch',
value: '',
options: [
{code: '0001', name: 'TEST 1', key: 1},
{code: '0002', name: 'TEST 2', key: 2},
{code: '0003', name: 'TEST 3', key: 3},
]
}
};
I then made a separate file for my dropdown component, it looks like this:
super(props);
this.state = {
modalVisible: false
};
}
render() {
return (
<>
<TouchableWithoutFeedback style={styles.refreshBtn} onPress={() => this.setState({ modalVisible: true })} >
<View style={styles.container} >
{
this.props.data.value ?
<Text style={styles.selectedText} >{this.props.data.value}</Text>
:
<Text style={styles.placeholderText} >{this.props.data.text}</Text>
}
<MaterialCommunityIcons name={'chevron-down'} size={30} color={Colors.grey} />
</View>
</TouchableWithoutFeedback>
<Modal
animationType="slide"
visible={this.state.modalVisible}
onRequestClose={() => {
this.setState({ modalVisible: false })
}}
>
<TouchableOpacity onPress={() => this.setState({ modalVisible: false })} style={{ flexDirection: "row", justifyContent: "flex-end", margin: 10, paddingLeft: 50}}>
<Ionicons name="md-close" size={30} />
</TouchableOpacity>
<FlatList
data={this.props.data.options}
keyExtractor={(item) => item.key.toString()}
renderItem={({ item }) => (
<TouchableOpacity style={styles.itemContainer} onPress={() => console.log('tapped'} >
<Text style={styles.itemText}>{item.code + ' ' + item.name}</Text>
</TouchableOpacity>
)}
/>
</Modal>
</>
);
}
}
And then back to my initial file, I am simply calling the component like this:
<DropDownMenu data={this.state.branchData}/>
How do I update the value in the branch data object in order to display the selected branch on the dropdown in order to indicate to the user that their choice has been selected instead of displaying the placeholder text which displays as long as value is = to an empty string.
You can pass down a state updating function as a prop to your DropDownMenu component, add this function to the same file where state has been initialized
function updateBranch(dataFromDropDownComponent) {
// modify branch data as required
// this.setState({...this.state, branchData: ... })
}
and then in JSX, pass it as a prop:
<DropDownMenu data={this.state.branchData} updateBranch={updateBranch}/>
Now in your DropDownMenu component, you can access and call the updateBranch function via this.props.updateBranch to update the state whenever required.
how can I access a single element from an array nested in a state like this
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
]
};
.....
<MyList.Provider
value={{
}}
>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.deleteItem(item)}
style={styles.Delete}
>
<MaterialCommunityIcons name="delete" color="red" size={30} />
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.props.navigation.navigate("Edit", item)}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() =>
this.props.navigation.navigate("Details", item)
}
/>
</>
)}
/>
</MyList.Provider>
how can I do this like this.state.post({title}) or some way else??
I need to use this values with context so I can share and change some particular data with between 2 screens. I know to pass data I need to use context or navigation.navigate("route name",item). But if I use navigation I won't able to edit it but how can I pass data in context value from array set, if I do this.state.post it will return whole list and if i do this.state.post[0].title it will return only title of that post. So how can i do this? Please help
You have to indicate the index of the object you’re trying to access in the array. For instance to access the first object in the array you can do this
this.state.post[0]
below is my solution which follows the logic i think you are trying to achieve. I have used a flatlist
Let me know if it helps
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
FlatList,
} from 'react-native';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
]
};
}
handleEdit(item) {
const { post } = this.state;
const extractIndex = post.findIndex(e => e.key === item.key);
const newPost = post[extractIndex];
this.props.navigation.navigate('Edit', { newPost })
this.setState({ post });
}
handleDelete(item) {
const { post } = this.state;
const newPost = post.filter(e => e.key !== item.key);
this.setState({ post: newPost });
}
renderItem = ({ item }) => {
return (
<View>
<Text>
{item.title}
</Text>
<TouchableOpacity key={item.key} onPress={this.handleEdit.bind(this, item)}>
<Text>Edit</Text>
</TouchableOpacity>
<TouchableOpacity key={item.key} onPress={this.handleDelete.bind(this, item)}>
<Text>Delete</Text>
</TouchableOpacity>
</View>
);
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.post}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
extraData={this.state}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
Use .map() function
Ex-
var cat_data = categories_list.map(function (item) {
var cat_data = categories_list.map(function (item) {
return {
name: item.Name,
thumb_url: item.PictureModel.ImageUrl,
cat_id: item.Id.toString(),
};
});
this.setState({
data: cat_data,
});
im new to react native so i just can storing data from input text to firebase and making a login form.
i want to make an apps for survey, there a form input for survey data then passing the id survey to the next form ( user form).
I can do that on CI or wordpress, but i cant do that on react native
the flow like this
Survey form --- send the id inserted firebase ---> User form --> Save Final Data
Edited for show my code
Survey Form
import React, { Component } from 'react';
import {
Button,
StyleSheet,
TextInput,
ScrollView,
ActivityIndicator,
View,
Text,
SafeAreaView,
TouchableOpacity
} from 'react-native';
import {Ionicons} from "#expo/vector-icons"
import firebase from 'firebase';
export default class PostScreen extends Component {
constructor() {
super();
this.dbRef = firebase.firestore().collection('surveys');
this.state = {
usia: '',
kab: '',
kec: '',
desa: '',
rw: '',
rt: '',
jekel: '',
tps: '',
isLoading: false
};
}
inputValueUpdate = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
storesurveys() {
if(this.state.usia === ''){
alert('Masukan usia anda!')
}else {
this.setState({
isLoading: true,
});
this.dbRef.doc(this.state.usia).set({
usia: this.state.usia,
kab: this.state.kab,
kec: this.state.kec,
desa: this.state.desa,
rw: this.state.rw,
rt: this.state.rt,
jekel: this.state.jekel,
tps: this.state.tps,
}).then((res) => {
this.setState({
usia: '',
kab: '',
kec: '',
desa: '',
rw: '',
rt: '',
jekel: '',
tps: '',
isLoading: false,
});
this.props.navigation.navigate('Dummy')
})
.catch((err) => {
console.error("Error found: ", err);
this.setState({
isLoading: false,
});
});
}
}
render() {
if(this.state.isLoading){
return(
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<TouchableOpacity onPress={()=> this.props.navigation.goBack()}>
<Ionicons name="md-arrow-back" size={24} color="#D8D9DB"></Ionicons>
</TouchableOpacity>
<TouchableOpacity>
<Text style={{fontWeight:"500"}}>Formulir surveys</Text>
</TouchableOpacity>
</View>
<ScrollView style={styles.inputForm}>
<View style={styles.inputGroup}>
<TextInput
placeholder={'usia'}
value={this.state.usia}
onChangeText={(val) => this.inputValueUpdate(val, 'usia')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'kab'}
value={this.state.kab}
onChangeText={(val) => this.inputValueUpdate(val, 'kab')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'kec'}
value={this.state.kec}
onChangeText={(val) => this.inputValueUpdate(val, 'kec')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'desa'}
value={this.state.desa}
onChangeText={(val) => this.inputValueUpdate(val, 'desa')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'rw'}
value={this.state.rw}
onChangeText={(val) => this.inputValueUpdate(val, 'rw')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'rt'}
value={this.state.rt}
onChangeText={(val) => this.inputValueUpdate(val, 'rt')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'jekel'}
value={this.state.jekel}
onChangeText={(val) => this.inputValueUpdate(val, 'jekel')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'tps'}
value={this.state.tps}
onChangeText={(val) => this.inputValueUpdate(val, 'tps')}
/>
</View>
<View style={styles.button}>
<Button
title='Add Survey'
onPress={() => this.storesurveys()}
color="#19AC52"
/>
</View>
</ScrollView>
</SafeAreaView>
);
}
}
User Form
NB : i need pass the survey form to my user form with the id inserted from survey
import React, { Component } from 'react';
import {
Button,
StyleSheet,
TextInput,
ScrollView,
ActivityIndicator,
View,
Text,
SafeAreaView,
TouchableOpacity
} from 'react-native';
import {Ionicons} from "#expo/vector-icons"
import firebase from 'firebase';
export default class PostScreen extends Component {
constructor() {
super();
this.dbRef = firebase.firestore().collection('penduduk');
this.state = {
nik: '',
nama: '',
tgl_lahir: '',
usia: '',
jekel: '',
survey: '',
isLoading: false
};
}
inputValueUpdate = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
storePenduduk() {
if(this.state.nik === ''){
alert('Masukan NIK anda!')
}else if(this.state.nama === ''){
alert('Masukan Nama anda!')
}else {
this.setState({
isLoading: true,
});
this.dbRef.doc(this.state.nik).set({
nik: this.state.nik,
nama: this.state.nama,
tgl_lahir: this.state.tgl_lahir,
usia: this.state.usia,
jekel: this.state.jekel,
survey : this.state.survey,
}).then((res) => {
this.setState({
nik: nik,
nama: '',
tgl_lahir: '',
usia: '',
jekel: '',
survey: '',
isLoading: false,
});
this.props.navigation.navigate('Dummy')
})
.catch((err) => {
console.error("Error found: ", err);
this.setState({
isLoading: false,
});
});
}
}
render() {
if(this.state.isLoading){
return(
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<TouchableOpacity onPress={()=> this.props.navigation.goBack()}>
<Ionicons name="md-arrow-back" size={24} color="#D8D9DB"></Ionicons>
</TouchableOpacity>
<TouchableOpacity>
<Text style={{fontWeight:"500"}}>Formulir Penduduk</Text>
</TouchableOpacity>
</View>
<ScrollView style={styles.inputForm}>
<View style={styles.inputGroup}>
<TextInput
placeholder={'nik'}
value={this.state.nik}
onChangeText={(val) => this.inputValueUpdate(val, 'nik')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'nama'}
value={this.state.nama}
onChangeText={(val) => this.inputValueUpdate(val, 'nama')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'tgl_lahir'}
value={this.state.tgl_lahir}
onChangeText={(val) => this.inputValueUpdate(val, 'tgl_lahir')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'usia'}
value={this.state.usia}
onChangeText={(val) => this.inputValueUpdate(val, 'usia')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'jekel'}
value={this.state.jekel}
onChangeText={(val) => this.inputValueUpdate(val, 'jekel')}
/>
</View>
<View style={styles.inputGroup}>
<TextInput
placeholder={'survey'}
value={this.state.survey}
onChangeText={(val) => this.inputValueUpdate(val, 'survey')}
/>
</View>
<View style={styles.button}>
<Button
title='Add User'
onPress={() => this.storePenduduk()}
color="#19AC52"
/>
</View>
</ScrollView>
</SafeAreaView>
);
}
}
Can someone giving me an example/source code/ documentation to do that?
thank you
First Screen
this.dbRef.doc(this.state.usia).set({
usia: this.state.usia,
kab: this.state.kab,
kec: this.state.kec,
desa: this.state.desa,
rw: this.state.rw,
rt: this.state.rt,
jekel: this.state.jekel,
tps: this.state.tps,
}).then((res) => {
const insertedId = res.id
this.setState({
usia: '',
kab: '',
kec: '',
desa: '',
rw: '',
rt: '',
jekel: '',
tps: '',
isLoading: false,
});
this.props.navigation.navigate('Dummy', {id: insertedId})
})
.catch((err) => {
console.error("Error found: ", err);
this.setState({
isLoading: false,
});
});
Second Screen :
render() {
if(this.state.isLoading){
const text = this.props.navigation.getParam('id', 'new id');
return(
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
Must follow all rules of this answer so you can id on next screen
You can get inserted id after add();
firebase.firestore().collection("SurveyForm").add({
// inserted values
}). then((docRef) => { const insertedId = docRef.id } })
I have created a form to upload the image and text field on the home screen but I am facing a problem that it's not updating the array and validation is failing due to that. I think something wrong with my implementation
AddPost.js
const validationSchema = Yup.object({
title: Yup.string().required().min(5).max(15).label("Title"),
des: Yup.string().required().min(15).max(200).label("Description"),
image: Yup.array().required().label("Image"),
});
class AddPost extends Component {
render() {
return (
<Formik
initialValues={{ title: "", des: "", image: [] }}
onSubmit={(values, actions) => {
actions.resetForm();
this.props.addPost(values);
}}
validationSchema={validationSchema}
>
{(value) => (
<View>
<FormImage />
<Text style={styles.error}>
{value.touched.image && value.errors.image}
</Text>
<TextInput
placeholder="Title"
onChangeText={value.handleChange("title")}
style={styles.input}
value={value.values.title}
onBlur={value.handleBlur("title")}
/>
<Text style={styles.error}>
{value.touched.title && value.errors.title}
</Text>
Here is my form field I think everything is right here
home.js
class Home extends Component {
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
image: null,
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState.post((currentPost) => {
return [posts, ...currentPost];
});
this.state.modal();
};
render() {
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={() => this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() => this.props.navigation.navigate("Edit", item)}
/>
</>
I think something wrong with the addPost method because I did it before with function base that time I only added text to the list and its worked but in class base I don't know to do it I just try the same way I did in function base
FormImage.js
class FormImage extends Component {
state = {
image: null,
hasCameraPermission: null,
};
async componentDidMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({ hasCameraPermission: status === "granted" });
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
this.setState({ image: result.uri });
}
};
render() {
const { image } = this.state;
return (
<TouchableWithoutFeedback onPress={this._pickImage}>
<View style={styles.container}>
{!image && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{image && <Image style={styles.image} source={{ uri: image }} />}
</View>
</TouchableWithoutFeedback>
);
}
}
after submiting
Iam assuming your addPost function logic is wrong,
Try the below code
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {...prevState, post: [...prevState.post, ...posts] };
});
this.state.modal();
};
Let me know incase you are getting the same error.
You are not updating images to formik so is normal you get the required error.
First in your AddPost Component pass down formikProps to FormImage component.
return (
<Formik
initialValues={{ title: "", des: "", image: [] }}
onSubmit={(values, actions) => {
// actions.resetForm(); --> comment this
this.props.addPost(values);
}}
validationSchema={validationSchema}
>
{(value) => (
<View>
<FormImage formikProps={value}/>
<Text style={styles.error}>
{value.touched.image && value.errors.image}
</Text>
<TextInput
placeholder="Title"
onChangeText={value.handleChange("title")}
style={styles.input}
value={value.values.title}
onBlur={value.handleBlur("title")}
/>
<Text style={styles.error}>
{value.touched.title && value.errors.title}
</Text>
In FormImage use that formikProps and call setFieldValue("image", result.uri) to update formik value for image.
class FormImage extends Component {
state = {
image: null,
hasCameraPermission: null,
};
async componentDidMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({ hasCameraPermission: status === "granted" });
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
this.setState({ image: result.uri });
this.props.formikProps.setFieldValue("image", result.uri);
}
};
render() {
const { image } = this.state;
return (
<TouchableWithoutFeedback onPress={this._pickImage}>
<View style={styles.container}>
{!image && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{image && <Image style={styles.image} source={{ uri: image }} />}
</View>
</TouchableWithoutFeedback>
);
}
}
In home
addPost = (posts) => {
console.log('add post');
posts.key = Math.random().toString();
this.setState((prevState) => {
return {...prevState, post: [...prevState.post, ...posts], modal:
true };
});
// this.state.modal();
};
I'm trying to create a list by dynamically adding the list items to an array in the state and then using the map operator to iterate over them. However, the new list items are only rendered after the second click on the button that handles the setState method. Any pointers on resolving this?
...
constructor(props) {
super(props);
this.state = {
requirements:[], // Placeholder array in state
currentRequirement
}
}
...
And in my render method I have this.
{
this.state.requirements.map((el,i) => (
<TouchableOpacity key={i}>
<BulletItem text={el}/>
</TouchableOpacity>
))
}
<FormInput
onChangeText={(value) => {
this.setState({ currentRequirement: value})}
}
placeholder="Enter a new requirement"
/>
<Button
title="Add Requirement"
onPress={() => {
this.onAddRequirementComponent()
}}
/>
The method for handling the setState is this.
onAddRequirementComponent() {
this.setState(previousState => ({
requirements: [...previousState.requirements, this.state.currentRequirement],
currentRequirement:''
}))
}
UPDATE : FULL COMPONENT
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Picker, TouchableOpacity } from 'react-native';
import { BulletItem, TagCloud } from "../components/index";
import { Actions } from "react-native-router-flux";
import {
Button,
Header,
FormInput,
FormLabel,
} from 'react-native-elements';
export default class ListScreen extends Component {
constructor(props) {
super(props);
this.state = {
jobtype: '',
level: '',
requirements: [],
benefits: [],
currentRequirement: '',
currentBenefit: ''
}
}
render() {
return (
<View style={styles.container}>
<Header
backgroundColor='#fff'
borderBottomWidth={0}
leftComponent={{ icon: 'corner-up-left', color: '#333', type: 'feather', onPress: () => { Actions.pop() } }}
centerComponent={{ text: 'Create New Job', fontFamily: 'VarelaRound-Regular', style: { color: '#333', fontSize: 18 } }}
rightComponent={{ icon: 'options', color: '#333', type: 'simple-line-icon' }} />
<ScrollView>
<FormLabel>Job Title</FormLabel>
<FormInput placeholder="e.g. Full Stack Javascript Developer"/>
<FormLabel >REQUIREMENTS</FormLabel>
{
this.state.requirements.map((el, i) => (
<TouchableOpacity key={i}><BulletItem containerStyle={{ backgroundColor: '#EFF0F2', borderRadius: 4 }} style={{ backgroundColor: '#EFF0F2' }} text={el} /></TouchableOpacity>
))
}
<FormInput
onChangeText={(value) => {
this.setState({ currentRequirement: value})}
}
placeholder="Enter a new requirement"
/>
<Button
title="Add Requirement"
onPress={() => {
this.onAddRequirementComponent()
}}
/>
<FormLabel style={{ fontFamily: 'VarelaRound-Regular', color: '#333' }} labelStyle={{ fontFamily: 'VarelaRound-Regular', color: '#333' }}>BENEFITS</FormLabel>
{
this.state.benefits.map((el, i) => (
<TouchableOpacity key={i}><BulletItem text={el} /></TouchableOpacity>
))
}
<FormInput value={this.state.currentBenefit} onChangeText={(value) => { this.setState({ currentBenefit: value }) }} placeholder="3 years experience developing Javascript apps" />
<Button title="Add" onPress={() => { this.onAddBenefitComponent() }}/>
<Picker selectedValue={this.state.jobtype}
style={{ height: 50, width: '100%', backgroundColor: '#EFF0F2' }}
onValueChange={(itemValue, itemIndex) => this.setState({ jobtype: itemValue })}>
<Picker.Item label="Full Time" value="fulltime" />
<Picker.Item label="Part Time" value="parttime" />
<Picker.Item label="Contract" value="contract" />
<Picker.Item label="Remote" value="remote" />
</Picker>
<Picker selectedValue={this.state.level}
style={{ height: 50, width: '100%', backgroundColor: '#EFF0F2' }}
onValueChange={(itemValue, itemIndex) => this.setState({ level: itemValue })}>
<Picker.Item label="Junior" value="junior" />
<Picker.Item label="Mid-Level" value="mid" />
<Picker.Item label="Management" value="management" />
<Picker.Item label="Senior" value="senior" />
</Picker>
</ScrollView>
</View>
);
}
onAddRequirementComponent() {
if (this.state.currentRequirement)
this.setState(previousState => ({
requirements: [...previousState.requirements, this.state.currentRequirement],
currentRequirement: ''
}))
}
onAddBenefitComponent() {
this.setState(previousState => ({
benefits: [...previousState.benefits, this.state.currentBenefit],
currentBenefit: ''
}))
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
}
});
This is the core logical part and works perfectly. I used only native elements like TextInput. The only change I made to make the TextInput to full controlled by adding value={this.state.currentRequirement} plus the suggestion of #Tholle for the usage of previousState.
class Test extends Component {
state = {
requirements: [],
currentRequirement: ''
}
onAddRequirementComponent() {
this.setState(previousState => ({
requirements: [...previousState.requirements, previousState.currentRequirement],
currentRequirement:''
}))
}
render() {
return(
<View>
<TextInput onChangeText={(value) => {
this.setState({ currentRequirement: value})}
}
value={this.state.currentRequirement}
/>
{ this.state.requirements.map((el,i) => (
<Text key={i}>{el}</Text>
))}
<Button
title="Add Requirement"
onPress={() => {
this.onAddRequirementComponent()
}}
/>
</View>
);
}
}