Flatlist doesn't render an array of Objects - react-native

Hello everybody i'm trying to render a list of objects to rapresent some letters, taken from a custom keyboard. my flatlist look like this:
<FlatList
horizontal={true}
data = {keyList}
renderItem = {({item}) =>
<View style={styles.singleBlock}>
<Text style={styles.textBlock}>{item.letter}</Text>
</View>
}
keyExtractor = {myKey}
/>
the data is taken from my state:
const [keyList, setKeyList] = useState([
{
'letter': "",
'state': "nonIndovinato",
'id': 1
},
{
'letter': "",
'state': "Indovinato",
'id': 2
},
{
'letter': "",
'state': "Indovinato",
'id': 3
},
{
'letter': "",
'state': "Indovinato",
'id': 4
},
{
'letter': "",
'state': "Indovinato",
'id': 5
}
]);
and updated by update function:
const updateData = (key) => {
const index = keyList.findIndex(item => item.id === key.id);
if(index === -1) return;
const item = keyList[index];
const updatedItem = {...item, letter: key.letter};
const updatedArray = keyList;
updatedArray[index] = updatedItem;
setKeyList(updatedArray);
};
the key value is something as follow:
{
'letter': 'A',
'id': 1
}
the data i see with console.log is right, for example if i press T it look like this:
{letter: 'T', state: 'nonIndovinato', id: 1},
{letter: '', state: 'Indovinato', id: 2},
{letter: '', state: 'Indovinato', id: 3},
{letter: '', state: 'Indovinato', id: 4},
{letter: '', state: 'Indovinato', id: 5}
the application look like this: https://i.stack.imgur.com/JhQiq.jpg
the upper part is the structure where it should be displayed the data, the lower is the expected result with mockup data.
if you need the style:
singleBlock: {
backgroundColor: 'grey',
width: width/6,
justifyContent: 'center',
alignItems: 'center',
margin: 1,
marginTop: '5%',
marginBottom: '5%',
marginRight: 2,
borderRadius: 1
},
textBlock: {
color: 'white',
fontSize: width/10,
fontWeight: 'bold'
}
Thanks to anyone who can help :)

The way you are updating your state is not correct. Try the following.
const updateData = (key) => {
const index = keyList.findIndex(item => item.id === key.id);
if(index === -1) return;
const item = keyList[index];
const updatedItem = {...item, letter: key.letter};
let updatedArray = [...keyList];
updatedArray[index] = updatedItem;
setKeyList(updatedArray);
};

Related

How to pass dynamic ref in react-native-deck-swiper in react native?

I'm not used to using ref, so i have a question. I'm using react-native-deck-swiper to display some cards. People are able to vote by swiping the cards. To be as clear as possible :
My swiper is displayed as an item with other items from multiple
types in my flatlist
My items are rendered conditionally by types of items, if my
item is a swiper type, im displaying a swiper, if it is a simple
text, i'm displaying a text etc...
So I potentially have multiple swipers in my flatlist
Here is the json to display my swipers :
{
"id": 577,
"type": "copernic",
"entity": {
"id": 715,
"str_id": "rCckubRTIDz2D3N5wcKW",
"display_name": "Force Républicaine",
"name": "Force Républicaine",
"title": "Dépense publique",
"description": null,
"type": 2,
"str_type": "Pour / Contre / Neutre",
"is_opened": 1,
"str_is_opened": "Les utilisteurs peuvent soumettre des propositions",
"order_propositions_by": 3,
"display_votes": 1,
"login_to_vote": 0,
"str_login_to_vote": "Les utilisateurs ne doivent pas se connecter pour voter",
"login_to_send_proposition": 1,
"str_login_to_send_proposition": "Les utilisateurs doivent se connecter pour envoyer une proposition",
"begins_at": "2021-03-02T17:45:55.000000Z",
"ends_at": null,
"propositions": [
{
"id": 6572,
"title": "Pensez-vous qu'il faille annuler la dette COVID ?",
"description": "",
"auteur": "Force Républicaine",
"type": 1,
"media_link": null,
"video_frame": null
},
{
"id": 6571,
"title": "Trouvez-vous la qualité des services publics en France à la hauteur du niveau de la dépense publique du pays ?",
"description": "",
"auteur": "Force Républicaine",
"type": 1,
"media_link": null,
"video_frame": null
}
]
},
"is_pinned": 0,
"created_at": "2021-03-18T13:27:03.000000Z"
},
So each swipers could have as a ref, the item.entity.id or the item.entity.id.
My swipers are displaying the item.entity.propositions as cards. Each card have thumbs to vote right, up or left. And I need a ref to do something as swiperRef.current.swipeRight() when we tap on a thumb or to tell the user that every cards from this swiper have been swiped by displaying a message. And now the message is displaying on all swipers and that't not what I want :)
Here's the code for my swiper :
if (
item.type === "copernic" &&
item.entity.str_type === "Pour / Contre / Neutre"
) {
return (
<View style={styles.swipperWrapper} key={item.id}>
{isSwipedAll ? (
<View style={styles.emptyCopernic}>
<View style={styles.emptyCopernicColor} />
<View style={styles.copContainer}>
<Text style={styles.copTitle}>
You have swiped all the cards! Thanx for your participation !
</Text>
</View>
</View>
) : (
<Swiper
ref={useSwiper}
//animateCardOpacity
containerStyle={styles.swiperContainer}
cards={item.entity.propositions}
renderCard={(card, index) => (
<CardCopernic
{...index}
copKey={card.id}
copTitle={card.title}
copDesc={card.description}
strid={strid}
onPressNo={() => swipeLeft(card.id, index)}
onPressMaybe={() => swipeTop(card.id, index)}
onPressYes={() => swipeRight(card.id, index)}
/>
)}
onSwipedLeft={(card) => handleNo(card)}
onSwipedTop={(card) => handleMaybe(card)}
onSwipedRight={(card) => handleYes(card)}
onSwipedAll={onSwipedAllCards}
cardIndex={cardIndex}
stackSize={3}
stackScale={5}
showSecondCard
backgroundColor="white"
cardVerticalMargin={2}
disableBottomSwipe
overlayLabels={{
left: {
title: "Contre",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "flex-end",
justifyContent: "flex-start",
marginTop: 30,
marginLeft: -30,
},
},
},
right: {
title: "Pour",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "flex-start",
justifyContent: "flex-start",
marginTop: 30,
marginLeft: 30,
},
},
},
top: {
title: "Neutre",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
},
},
}}
/>
)}
</View>
);
Here's one of the function to swipe the card to the left, right or top :
swipeLeft = async (cardId, index) => {
console.log("CARDINDEX : ", index);
const cardKey = cardId;
const strid = item.entity.str_id;
const token = await AsyncStorage.getItem("token");
useSwiper.current[strid].swipeLeft(cardId);
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
vote: "contre",
proposition_id: `${cardKey}`,
consultation_str_id: `${strid}`,
}),
};
try {
let response = await fetch(
`${c.API_URL_DEV}/copernic/vote/add`,
requestOptions
);
let json = await response.json();
if (index === item.entity.propositions.length - 1) {
setSwipedAll(true);
await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true));
}
return json;
} catch (error) {
console.error(error);
}
};
Any help is appreciated ! I'm a little bit stuck here and not too familiar with refs haha x
And my items are functional components :)
If you need more informations to help, let me know ! :)
Try encapsulating the related swiper code into a component. This will remove the need for dynamic refs and properly encapsulate state.
Something like:
function MySwiper({item}) {
const swiperRef = useRef(null);
const [isSwipedAll, setSwipedAll] = useState(false);
const swipeLeft = useCallback(async (cardId, index) => {
console.log("CARDINDEX : ", index);
const cardKey = cardId;
const strid = item.entity.str_id;
const token = await AsyncStorage.getItem("token");
swiperRef.current.swipeLeft(cardId);
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
vote: "contre",
proposition_id: `${cardKey}`,
consultation_str_id: `${strid}`,
}),
};
try {
let response = await fetch(
`${c.API_URL_DEV}/copernic/vote/add`,
requestOptions
);
let json = await response.json();
if (index === item.entity.propositions.length - 1) {
setSwipedAll(true);
await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true)); // TODO: index this somehow by the item
}
return json;
} catch (error) {
console.error(error);
}
}, [item]);
return (
<View style={styles.swipperWrapper} key={item.id}>
{isSwipedAll ? (
<View style={styles.emptyCopernic}>
<View style={styles.emptyCopernicColor} />
<View style={styles.copContainer}>
<Text style={styles.copTitle}>
You have swiped all the cards! Thanx for your participation !
</Text>
</View>
</View>
) : (
<Swiper
ref={useSwiper}
//animateCardOpacity
containerStyle={styles.swiperContainer}
cards={item.entity.propositions}
renderCard={(card, index) => (
<CardCopernic
{...index}
copKey={card.id}
copTitle={card.title}
copDesc={card.description}
strid={strid}
onPressNo={swipeLeft}
onPressMaybe={() => swipeTop(card.id, index)} // UPDATE
onPressYes={() => swipeRight(card.id, index)} // UPDATE
/>
)}
onSwipedLeft={(card) => handleNo(card)} // UPDATE
onSwipedTop={(card) => handleMaybe(card)} // UPDATE
onSwipedRight={(card) => handleYes(card)} // UPDATE
onSwipedAll={onSwipedAllCards}
cardIndex={cardIndex}
stackSize={3}
stackScale={5}
showSecondCard
backgroundColor="white"
cardVerticalMargin={2}
disableBottomSwipe
overlayLabels={...}
/>
)}
</View>
);
}
You'll need to create the other callbacks and fix they storing of state in AsyncStorage to be keyed based on each item.

Insert Data to State in 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()})
}

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>
);
}
}

React Native state is not getting updated

I want to update state on button click
this.state = {
legend: {
enabled: true,
textSize: 14,
form: 'CIRCLE',
horizontalAlignment: "RIGHT",
verticalAlignment: "CENTER",
orientation: "VERTICAL",
wordWrapEnabled: true
},
data: {
dataSets: [{
values: [{value: 45, label: 'Sandwiches'},
{value: 21, label: 'Salads'},
{value: 15, label: 'Soup'},
{value: 9, label: 'Beverages'},
{value: 15, label: 'Desserts'}],
label: 'Pie dataset',
}],
},
highlights: [{x:2}],
description: {
text: 'This is Pie chart description',
textSize: 14,
textColor: processColor('darkgray'),
}
};
I want to update values array of state by using following code but
it didn't work
const myvalues=this.state.data.dataSets[0].values.map(l => Object.assign({}, l));
myvalues[1].label = 'NEw sandwich';
this.setState({values: myvalues}, () => {
console.log(this.state.data.dataSets[0].values[1].label + " it worksss");
});
I am stuck in this
Check this
const myvalues = [] /*your new array*/
this.setState((state) =>
{
data: {
...state.data,
values: myvalues
}
});

In react native how to append fetch response array object in to render function?

I Need to Display Below the Array Data into Render Function :
I would Know how to loop the data and display it in Render.
[{
profileid: 1,
enabled: 1,
attachment: '',
id: 233,
topicid: 47,
tstamp: 'January, 21 2016 15:06:31 +1100',
body: 'to check orders'
}, {
profileid: 2,
enabled: 1,
attachment: '',
id: 233,
topicid: 47,
tstamp: 'January, 21 2016 15:06:31 +1100',
body: 'to check orders'
} ]
I hope I help you
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
gists : []
}
}
componentDidMount() {
fetch('http://rest.......')
.then(response => response.json())
.then(gists => this.setState({ gists }))
}
render(){
return (
<ul>
{this.state.gists.map(gist => (
<li key={gist.countryId}>{gist.name}</li>
))}
</ul>
)
}
}
Parent.propTypes = {
data: React.PropTypes.array
}
Here is an example.
import React from 'react'
import { View, Text } from 'react-native'
...
const data = [{
profileid: 1,
enabled: 1,
attachment: '',
id: 233,
topicid: 47,
tstamp: 'January, 21 2016 15:06:31 +1100',
body: 'to check orders'
}, {
profileid: 2,
enabled: 1,
attachment: '',
id: 233,
topicid: 47,
tstamp: 'January, 21 2016 15:06:31 +1100',
body: 'to check orders'
} ]
...
render() {
return (
<View>
{data.map((dataItem) =>
<View key={dataItem.profileid}>
<Text>{dataItem.profileId}</Text>
<Text>{dataItem.enabled}</Text>
<Text>{dataItem.attachment}</Text>
<Text>{dataItem.id}</Text>
<Text>{dataItem.topicid}</Text>
<Text>{dataItem.tstamp}</Text>
<Text>{dataItem.body}</Text>
</View>
)}
</View>
)
}