Insert Data to State in React Native - react-native

I have a list data and a input type for add data, so I make state for save data and rendering it. I want when I type text in TextInput then I enter so data will added. but for this issue, screen must to be refresh for data added.
const [dataSubjects, setDataSubject] = useState([
{
id: "PPKN",
name: "Pendidikan Pancasila dan Kewarganegaraan (PPKn)",
},
{
id: "BI",
name: "Bahasa Indonesia (BI)",
},
{
id: "MAT",
name: "Matematika (MAT)",
},
{
id: "IPA",
name: "Ilmu Pengetahuan Alam (IPA)",
},
{
id: "IPS",
name: "Ilmu Pengetahuan Sosial (IPS)",
},
{
id: "SBDP",
name: "Seni Budaya dan Prakarya (SBdP)",
},
{
id: "PJOK",
name: "Pendidikan Jasmani, Olahraga, dan Kesehatan (PJOK)",
},
])
const HandleSubmit = (name) => {
setText("")
setDataSubject((prevSubject) => {
return [{ name, id: Math.random().toString() }, ...prevSubject]
})
}
This is a code for state data and function add data
<TextInput
visible={inputSubject}
mode="outlined"
placeholder="Type other subject…"
underlineColor="transparent"
value={text}
style={{
backgroundColor: theme.colors.surface,
fontSize: 14,
borderRadius: 4,
flex: 1,
}}
onChangeText={handleChangeText}
onSubmitEditing={() => HandleSubmit(text)}
/>
this is a TextInput code

Are you trying to add whatever you type in <TextInput/> as a new item in dataSubjects? If you are you can add an item to an array by using either of the two:
Array.prototype.unshift() to addd an item at the start of the array
Array.prototype.push() to add an item at the end of the array
Specifically, you can try something like this:
const HandleSubmit = (name) => {
setText("")
setDataSubject(dataSubjects.unshift({name: name, id: Math.random().toString()})
}

Related

What config and options do I need for react-native-highcharts to make a highstock OHLC graph?

I've been going through HighStock API to try and find which config and options I need to pass to the ChartView component in react-native-highcharts to draw my graph. I'm having a hard time finding what combination of config and options will get my desired result, things like series, dataGrouping, etc... . My data is a 2 dimensional array with 4 values for OHLC. My desired result is the photo at the top of this stackoverflow.
Here is my code so far.
class OHLC extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "OHLC",
headerLeft: (
<TouchableOpacity
style={NavStyles.headerButton}
onPress={() => navigation.openDrawer()}>
<Icon name="bars" size={20} />
</TouchableOpacity>
),
})
render() {
var Highcharts='Highcharts';
var conf={
title: {
text: 'Stock Name'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
// tooltip: {
// formatter: function () {
// return '<b>' + this.series.name + '</b><br/>' +
// Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
// Highcharts.numberFormat(this.y, 2);
// }
// },
legend: {
enabled: false
},
// exporting: {
// enabled: false
// },
series: [{
type: 'ohlc',
name: 'AAPL Stock Price',
data: (function () {
let arrays = aExtractFromJson(data,'data', null,null);
arrays = ohlcExtractor(arrays);
return arrays;
// look at toFixed method for number to limit decimal point
}()),
dataGrouping: {
units: [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]]
}
}]
};
const options = {
global: {
useUTC: false
},
lang: {
decimalPoint: ',',
thousandsSep: '.'
}
};
return (
<View>
<ChartView style={{height:300}} config={conf} options={options} stock={true} ></ChartView>
//To see if anything gets rendered.
<Text>HELLO DAVID!</Text>
</View>
);
}
}
After further research, I was able to find the config and options needed to create an OHLC Graph using the ChartView component in react-native-highcharts. I encountered some issues with rendering a blank screen so I added javaScriptEnabled={true} domStorageEnabled={true} originWhitelist={['']} to my ChartView.
In the config the essentials:
series with type: 'ohlc' and data: [[1,2,3,4],[2,3,4,5]] inside.
In options, no arguments are required, I left it as options='' in the ChartView.
Don't forget to add stock={true} in ChartView
My code, basic example:
import React, {Component} from 'react';
import {View} from 'react-native';
import ChartView from 'react-native-highcharts';
class OHLC extends React.Component {
constructor(props) {
super(props);
}
render() {
var Highcharts='Highcharts';
var conf={
chart: {
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
type: 'ohlc',
name: 'Random data',
/*Open, high,low,close values in a two dimensional array(two days)*/
data: [[1,2,3,4],[2,3,4,5]],
}]
};
return (
<View style={{borderRadius: 4, marginTop: 30,}}>
<ChartView style={{height:500}} config={conf} javaScriptEnabled={true} domStorageEnabled={true} originWhitelist={['']} stock={true} options=''></ChartView>
</View>
);
}
}

Set Selected items in react native multi select

I want to select the selected items which i already select & save at backend after that if i get response then set already selected those items which i have set in react native multi select
here is my code for react native multiselect
//Example Multiple select / Dropdown / Picker in React Native
import React, { Component } from "react";
//Import React
import { View, Text, Picker, StyleSheet, SafeAreaView } from "react-native";
//Import basic react native components
import MultiSelect from "react-native-multiple-select";
//Import MultiSelect library
//Dummy Data for the MutiSelect
this.items = [
{ id: "1", name: "America" },
{ id: "2", name: "Argentina" },
{ id: "3", name: "Armenia" },
{ id: "4", name: "Australia" },
{ id: "5", name: "Austria" },
{ id: "6", name: "Azerbaijan" },
{ id: "7", name: "Argentina" },
{ id: "8", name: "Belarus" },
{ id: "9", name: "Belgium" },
{ id: "10", name: "Brazil" }
];
export default class App extends Component {
state = {
//We will store selected item in this
selectedItems: [
{ id: "1", name: "America" },
{ id: "2", name: "Argentina" },
{ id: "3", name: "Armenia" },
{ id: "4", name: "Australia" }
]
};
onSelectedItemsChange = selectedItems => {
this.setState({ selectedItems });
//Set Selected Items
};
render() {
const { selectedItems } = this.state;
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1, padding: 30 }}>
<MultiSelect
hideTags
items={items}
uniqueKey="id"
ref={component => {
this.multiSelect = component;
}}
onSelectedItemsChange={this.onSelectedItemsChange}
selectedItems={selectedItems}
selectText="Pick Items"
searchInputPlaceholderText="Search Items..."
onChangeInput={text => console.log(text)}
tagRemoveIconColor="#CCC"
tagBorderColor="#CCC"
tagTextColor="#CCC"
selectedItemTextColor="#CCC"
selectedItemIconColor="#CCC"
itemTextColor="#000"
displayKey="name"
searchInputStyle={{ color: "#CCC" }}
submitButtonColor="#48d22b"
submitButtonText="Submit"
/>
<View>
{this.multiSelect &&
this.multiSelect.getSelectedItemsExt(selectedItems)}
</View>
</View>
</SafeAreaView>
);
}
}
Got it.
this.state={
selectedData: "158" // list of id here(without space, that is your response of api)
};
<MultiSelect
.....
.....
selectedItems={selectedData}
/>
<View>
{this.multiselect ? this.multiSelect.getSelectedItemsExt(selectedData): null}
</View>
I had this same issue and I figured out how to preset selections by using parts of the accepted answer.
I learned that selectedItems is a list of whatever is set as the uniqueKey in the MultipleSelect props.
For example, if you put the uniqueKey as a numbered id of each list member and you wanted the second member set as selected, you would have selectedItems = {[ "2" ]}
I hope this makes sense.

How to set multiple select with #shoutem/ui DropDownMenu?

I use DropDownMenu and take a reference from official doumcn https://shoutem.github.io/docs/ui-toolkit/components/dropdown-menu
I want to set two DropDownMenu the first is for zone and the second is for city, if user select the zone like East the second DropDownMenu should set the value E1、E2
Here is my code:
import React, { Component } from 'react';
import { View } from 'react-native';
import { DropDownMenu, Text } from '#shoutem/ui';
class TestConfirm extends Component {
constructor(props) {
super(props);
this.state = {
zone: [
{
id: 0,
brand: "North",
models:
{
model: "Audi R8",
image: {
url: "https://shoutem.github.io/img/ui-toolkit/dropdownmenu/Audi-R8.jpg"
},
description: "North Description"
},
children: [{
name: "N1",
id: 10,
},{
name: "N2",
id: 17,
}]
},
{
id: 1,
brand: "West",
models: {
model: "Chiron",
image: {
url: "https://shoutem.github.io/img/ui-toolkit/dropdownmenu/Chiron.jpg"
},
description: "West Description"
},
children: [{
name: "W1",
id: 10,
},{
name: "W2",
id: 17,
}]
},
{
id: 2,
brand: "East",
models: {
model: "Dodge Viper",
image: {
url: "https://shoutem.github.io/img/ui-toolkit/dropdownmenu/Dodge-Viper.jpg"
},
description: "East Description"
},
children: [{
name: "E1",
id: 10,
},{
name: "E2",
id: 17,
}]
},
],
}
}
render() {
const selectedZone = this.state.selectedZone || this.state.zone[0];
console.log('selectedZone =>');
console.log(selectedZone);
console.log('selectedZone.children =>');
console.log(selectedZone.children);
return (
<Screen>
<DropDownMenu
styleName="horizontal"
options={this.state.zone}
selectedOption={selectedZone ? selectedZone : this.state.zone[0]}
onOptionSelected={(zone) => this.setState({ selectedZone: zone })}
titleProperty="brand"
valueProperty="cars.model"
/>
<Text styleName="md-gutter-horizontal">
{selectedZone ?
selectedZone.models.description :
this.state.zone[0].models.description}
</Text>
<DropDownMenu
styleName="horizontal"
options={selectedZone.children}
selectedOption={selectedZone ? selectedZone : this.state.zone[0].children}
onOptionSelected={(city) => this.setState({ selectedZone: city })}
titleProperty="name"
valueProperty="cars.model"
/>
</Screen>
);
}
}
export default TestConfirm;
Here is my screen look like this:
If i select East it will show error
Invalid `selectedOption` {"id":2,"brand":"East","models":{"model":"Dodge Viper","image":{"url":"https://shoutem.github.io/img/ui-toolkit/dropdownmenu/Dodge-Viper.jpg"},"description":"East Description"},"children":[{"name":"E1","id":10},{"name":"E2","id":17}]}, DropDownMenu `selectedOption` must be a member of `options`.Check that you are using the same reference in both `options` and `selectedOption`.
I check my console.log will look like this:
The key children under the name is what i want to put it into my second DropDownMenu
I have no idea how to do next step. Any help would be appreciated.
Thanks in advance.
selectedOption property for the DropDownMenu component expects a single object but this.state.zone[0].children is an array. You can change it to this.state.zone[0].children[0] to fixed the problem.
Also when you change the city dropdown you are updating the zone value in state. This will cause a bug. Try fixing it with setting a different value in state and checking that value for the city dropdown
Sample
render() {
const { zone, selectedZone, selectedCity } = this.state
return (
<Screen>
<DropDownMenu
styleName="horizontal"
options={zone}
selectedOption={selectedZone || zone[0]}
onOptionSelected={(zone) =>
this.setState({ selectedZone: zone, selectedCity: zone.children[0] } )
}
titleProperty="brand"
valueProperty="cars.model"
/>
<Text styleName="md-gutter-horizontal">
{selectedZone ?
selectedZone.models.description :
this.state.zone[0].models.description}
</Text>
<DropDownMenu
styleName="horizontal"
options={selectedZone ? selectedZone.children : zone[0].children } // check if zone selected or set the defaul zone children
selectedOption={selectedCity || zone[0].children[0] } // set the selected city or default zone city children
onOptionSelected={(city) => this.setState({ selectedCity: city })} // set the city on change
titleProperty="name"
valueProperty="cars.model"
/>
</Screen>
);
}

Access property value after setting it with setNativeProps

I'm trying to toggle the display of dynamically created components in React Native (with Coffeescript). The components are created conform the structure of a JSON object and each component has a ref attribute with the according id so i can access the specific component like so: this.refs[ id ]
I have the following function to change the display of the component
changeDisplay: ( id ) ->
this.refs[ id ].setNativeProps( {
display: 'flex'
} );
This works fine when i want to change the initial display, but i want to toggle the display between none and flex (based on the current state).
Because i don't know how many items are rendered on forehand i can't (or don't know how to) define states for them.
I tried the following, but i somehow can't get the new display state back after setting it with setNativeProps()
changeDisplay: ( id ) ->
if this.refs[ id ].props.style.display is 'none'
this.refs[ id ].setNativeProps( {
display: 'flex'
} );
else
this.refs[ id ].setNativeProps( {
display: 'none'
} );
Initially this.refs[ id ].props.style.display returns the state the component is in when i load the view (= none), but after i run the function above the display state is visually changed (the component shows up), but this.refs[ id ].props.style.display still return the initial state none
Why?
EDIT:
Below is my (stripped) component (as requested). I want to toggle the display of the child tasks in a certain project. So if i tap the project Project 1, i want to toggle the display state of the tasks 1 & 2.
import React from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
ScrollView
} from 'react-native';
import {
Icon,
} from 'react-native-elements';
class ListTasks extends React.Component
constructor: ( props ) ->
super props
this.data =
list: [
{
id: 1
name: 'Project 1'
type: 'project'
parent: null
},{
id: 2
parent: 1
name: 'Task 1'
type: 'task'
},{
id: 3
parent: 1
name: 'Task 2'
type: 'task'
},{
id: 4
name: 'Project 2'
type: 'project'
parent: null
},{
id: 5
parent: 4
name: 'Task 3'
type: 'task'
},{
id: 6
parent: 4
name: 'Task 4'
type: 'task'
}
]
toggleDisplay: ( id ) ->
if this.refs[ id ].props.style.display is v[ 0 ]
this.refs[ id ].setNativeProps( {
display: 'flex'
} );
else
this.refs[ id ].setNativeProps( {
display: 'none'
} );
renderList: ( data ) ->
<View>
<View>
<TouchableOpacity onPress={() => this.toggleDisplay( data.id )}>
<Text>{data.name}</Text>
</TouchableOpacity>
</View>
<View ref={data.id} style={display: 'none'}>
{ this.renderTask cor for cor in this.data.list when cor.parent is data.id }
</View>
</View>
renderTask: ( data ) ->
<View>
<Text>{data.name}</Text>
</View>
render: ->
<View>
<ScrollView style={height:'100%'}>
{ this.data.list.map( ( data ) =>
if data.type == 'project'
this.renderList( data )
) }
</ScrollView>
</View>
export default ListTasks
Your data structure is not very optimal for storing data that clearly has a 2D sectional kind of relationships. I have modified the data structure a bit below.
DOM manipulation is also not the React way. Instead we use states to manage the visibility and properties of the elements.
A working example of a sectional collapsible list:
import React from 'react';
import { Text, TouchableOpacity, SectionList } from 'react-native';
const data = [
{
id: 1,
name: 'Project 1',
type: 'project',
data: [
{
id: 2,
name: 'Task 1',
type: 'task',
},
{
id: 3,
name: 'Task 2',
type: 'task',
},
],
},
{
id: 4,
name: 'Project 2',
type: 'project',
data: [
{
id: 5,
name: 'Task 3',
type: 'task',
},
{
id: 6,
name: 'Task 4',
type: 'task',
},
],
},
];
class ListTasks extends React.Component {
state = {
list: data,
show: {},
};
render() {
// SectionList is used instead of ScrollView as it has better performance
return (
<SectionList
style={{ marginTop: 50 }}
sections={this.state.list}
renderItem={({ item, section }) =>
// render null if show state for the section is falsy
(this.state.show[section.id] ? <Text style={{ padding: 10 }}>{item.name}</Text> : null)
}
renderSectionHeader={({ section }) => (
<TouchableOpacity
style={{ paddingVertical: 10, margin: 10, backgroundColor: 'grey' }}
onPress={() =>
this.setState((prevState) => ({
show: {
...prevState.show,
// toggle the show state for the seciton
[section.id]: !prevState.show[section.id],
},
}))
}
>
<Text>{section.name}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item.id}
/>
);
}
}
export default ListTasks;

React native component does not react to mobx observable data change

so I started to build a new app with react native and mobx.
I have a flat list component that gets his state data from the mobx store list. and when i'm adding new item to the mobx list, it won't re render the flat list view.
here is my code:
List Component:
#inject('TravelStore')
#observer
class TripsList extends Component {
constructor(props) {
super(props);
this.state = {
trips_list: props.TravelStore.trips_list
}
};
// set the navigation bar options
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
title: 'Your Trips',
headerRight: (
<Button transparent primary onPress={ params.addNewTrip }>
<Icon name='ios-add' />
</Button>
)
};
};
// connect between component functions to header
componentDidMount() {
this.props.navigation.setParams({
addNewTrip: this._addNewTrip.bind(this),
});
}
_addNewTrip() {
this.props.TravelStore.addNewTrip('bla')
}
_renderListItem({ item }) {
return (
<TripsListItem details={item} navigation={this.props.navigation}/>
);
};
render() {
return (
<Container>
<FlatList
data = {this.state.trips_list}
renderItem = {this._renderListItem.bind(this)}
keyExtractor={(item, index) => index}
/>
</Container>
);
};
}
mobx store:
class ObservableTravelListStore {
#observable trips_list = [
{
name: 'to denver',
trip_cost: 400,
buying_list: [
{ name: 'pizza', price: 10 },
{ name: 'burger', price: 40 },
{ name: 'ipad', price: 44 },
{ name: 'bus', price: 45 },
]
},
{
name: 'to yafo',
trip_cost: 30,
buying_list: [
{ name: 'na na na', price: 10 },
{ name: 'burger', price: 40 },
]
},
{
name: 'to tel aviv',
trip_cost: 50,
buying_list: [
{ name: 'na na na', price: 10 },
{ name: 'no no no', price: 40 },
]
},
]
#action addNewTrip (trip_data) {
this.trips_list.push({
name: 'newTrip',
trip_cost: 6060,
buying_list: [
{ name: 'na na na', price: 10 },
{ name: 'burger', price: 40 },
]
})
console.log(this.trips_list[3])
}
}
const TravelStore = new ObservableTravelListStore()
export default TravelStore
any idea why the TripsList component won't rerender when addNewTrip function is called?
the problem is that you are not listening to the real observable but to a copy of it, you save in state in the constructor.
<FlatList
data = {this.state.trips_list}//change this
renderItem = {this._renderListItem.bind(this)}
keyExtractor={(item, index) => index}
/>
<FlatList
data = {this.props.TravelStore.trips_list}//change to this
renderItem = {this._renderListItem.bind(this)}
keyExtractor={(item, index) => index}
/>
the render function is like autobind of mobx and react to changes in the observable if it's a render function of an observer
if you want to react to inner changes in the items of the list,
you should add an observable scheme and this should do the trick,
something like this:
class TripModel {
#observable name = ''
#observable trip_cost = 0
#observable buying_list = []
constructor(name, cost, buy_list){
this.name = name
this.trip_cost = cost
this.buying_list = buy_list
}
/* class functions*/
}
class ObservableTravelListStore {
#observable trips_list = [
new Trip(
'to denver',
400,
[
{ name: 'pizza', price: 10 },
{ name: 'burger', price: 40 },
{ name: 'ipad', price: 44 },
{ name: 'bus', price: 45 },
]
),
new Trip(
'to yafo',
30,
[
{ name: 'na na na', price: 10 },
{ name: 'burger', price: 40 },
]
),
new Trip(
'to tel aviv',
50,
[
{ name: 'na na na', price: 10 },
{ name: 'burger', price: 40 },
]
)
]
#action addNewTrip (trip_data) {
this.trips_list.push(new Trip(
'newTrip',
6060,
[
{ name: 'na na na', price: 10 },
{ name: 'burger', price: 40 },
]
))
}
}
const TravelStore = new ObservableTravelListStore()
export default TravelStore
this is just better planning for reactive apps, so on change to inner content of the items in the list you will react to this change
hope that helps
Its an old post, but I also got stuck with something similar recently. Adding extraData in Flatlist prop list helped me.
<FlatList
data = {this.props.TravelStore.trips_list}
renderItem = {this._renderListItem.bind(this)}
keyExtractor={(item, index) => index}
extraData={this.props.TravelStore.trips_list.length} // list re-renders whenever the array length changes
/>
And as #Omri pointed out, you shouldn't be storing the observable in the Component state but make changes to it directly.