React-Native Edit Text in the Array - react-native

I'm creating a listing app and I want to edit this listed text. I dont know how to do this.
editTodo(key)
{this.state.todoList.splice(key,1);
this.setState({todoText: this.state.todoText})
and other thing is
let tds = this.state.todoList.map((val,key) => {
return <ToDo key = {key}
keyval = {key}
val = {val}
deleteTodo = { () => this.deleteTodo(key)} />
});
but It does not work. I'm new at React-native.

If you want to remove an item from a list, you can use this code:
let t = this.state.todoList;
t.splice(key, 1);
this.setState({todoList: t})
If you don't know index of item to remove, you can use this:
let t = this.state.todoList;
let i = t.indexOf(val, 0);
if (i > -1){ //if val exist in list
t.splice(i, 1);
}
this.setState({todoList: t})
I hope this can help you.
EDIT:
To edit a cell of an array, you can use this:
let t = this.state.todoList;
t[key] = 'new value'
this.setState({todoList: t})
if todoList is an array of objects, for example:
let todoList: [ {id:1, name:'a'}, {id:2, name:'b'}, {id:3, name:'c'}]
You can use this:
let t = this.state.todoList;
t[key].name = 'new name'
t[key].id = newID
this.setState({todoList: t})
or you can pass an object and assign it to cell like this:
Edit = (newObj) => {
let t = this.state.todoList;
t[key] = newObj
this.setState({todoList: t})
}

Related

for loop only iterating twice with axios

const [Datalist,setDatalist] = useState([]);
useEffect(() => {
axios.get( 'http://0.0.0.0:8000/api/v1/questions/history/1')
.then(response => {
const questions = response.data;
const datalist = [];
for (let i = 0; i < questions.length - 1; i++) {
const data = new Object();
data.isExpanded = false;
data.question_id = questions[i].id;
data.question = questions[i].content;
data.type = questions[i].type;
data.commentType = questions[i].comment_type;
data.answer = [];
datalist.push(data);
}
setDatalist(datalist);
});
},[]);
I have three questions in my database currently. The for loop should be iterating through 0 to 2, however, it is only iterating twice.
And I'm also having problems putting the data into Datalist.
Anybody know where the issue is??
Thanks in advance!!
Change your for loop to this:
for (let i = 0; i < questions.length; i++)
Since you are iterating over each question you receive, you could use the map-method (if your environment supports ES6-Syntax - but since you're using react, it most likely dooes).
From the MDN Docs:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
With map, your code could look like this:
(Also note the removal of const data = new Object();. you can initialize an object and assign its properties/values at the same time)
const [Datalist,setDatalist] = useState([]);
useEffect(() => {
axios.get( 'http://0.0.0.0:8000/api/v1/questions/history/1')
.then(response => {
const questions = response.data;
const datalist = questions.map(question => {
return {
isExpanded: false;
question_id: question.id;
question: question.content;
type: question.type;
commentType: question.comment_type;
answer: [];
};
});
setDatalist(datalist);
});
},[]);

Material-table lookup does not work with a dynamically constructed variable

I am passing a variable constructed as the following code for Lookup.
let classLookup = {};
let classOptions = responseData.classOptions;
for (var i = 0; i < classOptions.length; ++i) {
classLookup[i] = classOptions[i];
}
Here responseData.classOptions is an array:
[{0: "A"}, {1:"B"}....]
classLookup is then constructed as:
{0: "A", 1: "B" ....}
Passing classLookup to material-table does not get recognized.
{
title: 'Class',
field: 'Class',
lookup: classLookup
},
However, if I hard coded classLookup as
let classLookup = {0: "A", 1: "B" ....}
It works fine.
I am clueless what was wrong with the variable I constructed. Please help. Thanks in advance.
Issue found. I shall use useState to set classLookup.
const [classLookup, setClassLookup] = useState();
let tmp = {};
let classOptions = responseData.classOptions;
for (var i = 0; i < classOptions.length; ++i) {
tmp[i] = classOptions[i];
}
setClassLookup(tmp)

How to check number exists in Firebase Database? - react-native-firebase

I use react native through firebase database
I have a database creating products each product has a number
I want to take a number and compare it with the product number
And if there is then I want to get a product
the function its give me my correct name but where i use it on render its not found the variable (name)
getAllContact = async key => {
let barCodeData2 = this.props.navigation.state.params.barcodeData
let self = this;
let contactRef = firebase.database().ref()
contactRef.on("value", dataSnapsot => {
if (dataSnapsot.val()) {
let contactResult = Object.values(dataSnapsot.val())
let contactKey = Object.keys(dataSnapsot.val())
contactKey.forEach((value, key) => {
contactResult[key]["key"] = value
})
self.setState({
fname: contactResult.fname,
data: contactResult.sort((a, b) => {
var nameA = a.barcode
var nameB = barCodeData2
const name = a.fname
console.log(`${nameA} What numers issssssss`);
if (nameA == nameB) {
alert(`${name} ........`)
console.log(`${nameA == nameB}is Equqlqlqlql`);
return name
}
}),
})
}
})
}
render() {
let t=this.state.name
alert(`${t} how?`)// is give Not found
// let d = this.props.navigation.state.params.barcodeData
return (
)
}
When you try such a comparison query i.e.
let ref = firebase.firestore();
ref.collection('zoo')
.where("id", "==", myID)
.get()
.then((snapshot) => {
console.log(snap.empty); //this will denote if results are empty
snapshot.forEach(snap => {
console.log(snap.exists); //alternatively this will also tell you if it is empty
})
})
well what you can do is run query based on you product no and if there's a product you will a product if there's none you will get an empty array.
read firebase documentation on queries
https://firebase.google.com/docs/reference/js/firebase.database.Query

Why is my data filter function returning empty?

When I hit the button messageIncompleted it works, but when I click the messageCompleted button the data disappears. Can you help me to solve this problem?
messageIncompleted() {
this.messages = this.messages.filter(messages => ! messages.completed );
this.disabledIncomplete = true;
},
messageCompleted() {
this.messages = this.messages.filter(messages => messages.completed );
this.disabledComplete = true;
}
When you click on messageIncompleted, the this.messages array is updated with items which have messages.completed = false. When you click on messageCompleted, the messages array won't have any items with messages.completed = true.
To fix this, you can create another property called filteredMessages to store and display the messages based on criteria. By default, you can set it to this.messages. This way, messages array won't be directly mutated.
messageIncompleted() {
this.filteredMessages = this.messages.filter(messages => !messages.completed);
this.disabledIncomplete = true;
},
messageCompleted() {
this.filteredMessages = this.messages.filter(messages => messages.completed);
this.disabledComplete = true;
}

Vue.js list not updating when data changes

i'm trying re-organised a list of data. I have given each li a unique key, but still, no luck!
I have had this working before exactly like below, think i'm cracking up!
let app = new Vue({
el: '#app',
data: {
list: [
{ value: 'item 1', id: '43234r' },
{ value: 'item 2', id: '32rsdf' },
{ value: 'item 3', id: 'fdsfsdf' },
{ value: 'item 4', id: 'sdfg543' }
]
},
methods: {
randomise: function() {
let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
this.list = input;
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in list" :key="item.id">{{ item.value }}</li>
</ul>
Randomize
</div>
Edit:
Thanks for the answers, to be honest the example I provided may not have been the best for my actual issue I was trying to solve. I think I may have found the cause of my issue.
I'm basically using a similar logic as above, except i'm moving an array of objects around based on drag and drop, this works fine with normal HTML.
However, i'm using my drag and drop component somewhere else, which contains ANOTHER component and this is where things seem to fall apart...
Would having a component within another component stop Vue from re-rendering when an item is moved within it's data?
Below is my DraggableBase component, which I extend from:
<script>
export default {
data: function() {
return {
dragStartClass: 'drag-start',
dragEnterClass: 'drag-enter',
activeIndex: null
}
},
methods: {
setClass: function(dragStatus) {
switch (dragStatus) {
case 0:
return null;
case 1:
return this.dragStartClass;
case 2:
return this.dragEnterClass;
case 3:
return this.dragStartClass + ' ' + this.dragEnterClass;
}
},
onDragStart: function(event, index) {
event.stopPropagation();
this.activeIndex = index;
this.data.data[index].dragCurrent = true;
this.data.data[index].dragStatus = 3;
},
onDragLeave: function(event, index) {
this.data.data[index].counter--;
if (this.data.data[index].counter !== 0) return;
if (this.data.data[index].dragStatus === 3) {
this.data.data[index].dragStatus = 1;
return;
}
this.data.data[index].dragStatus = 0;
},
onDragEnter: function(event, index) {
this.data.data[index].counter++;
if (this.data.data[index].dragCurrent) {
this.data.data[index].dragStatus = 3;
return;
}
this.data.data[index].dragStatus = 2;
},
onDragOver: function(event, index) {
if (event.preventDefault) {
event.preventDefault();
}
event.dataTransfer.dropEffect = 'move';
return false;
},
onDragEnd: function(event, index) {
this.data.data[index].dragStatus = 0;
this.data.data[index].dragCurrent = false;
},
onDrop: function(event, index) {
if (event.stopPropagation) {
event.stopPropagation();
}
if (this.activeIndex !== index) {
this.data.data = this.array_move(this.data.data, this.activeIndex, index);
}
for (let index in this.data.data) {
if (!this.data.data.hasOwnProperty(index)) continue;
this.data.data[index].dragStatus = 0;
this.data.data[index].counter = 0;
this.data.data[index].dragCurrent = false;
}
return false;
},
array_move: function(arr, old_index, new_index) {
if (new_index >= arr.length) {
let k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing
}
}
}
</script>
Edit 2
Figured it out! Using the loop index worked fine before, however this doesn't appear to be the case this time!
I changed the v-bind:key to use the database ID and this solved the issue!
There are some Caveats with arrays
Due to limitations in JavaScript, Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
When you modify the length of the array, e.g. vm.items.length = newLength
To overcome caveat 1, both of the following will accomplish the same as vm.items[indexOfItem] = newValue, but will also trigger state updates in the reactivity system:
Vue.set(vm.items, indexOfItem, newValue)
Or in your case
randomise: function() {
let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
Vue.set(input, randomIndex, input[i]);
Vue.set(input, i, itemAtIndex);
}
this.list = input;
}
Here is an working example: Randomize items fiddle
Basically I changed the logic of your randomize function to this:
randomize() {
let new_list = []
const old_list = [...this.list] //we don't need to copy, but just to be sure for any future update
while (new_list.length < 4) {
const new_item = old_list[this.get_random_number()]
const exists = new_list.findIndex(item => item.id === new_item.id)
if (!~exists) { //if the new item does not exists in the new randomize list add it
new_list.push(new_item)
}
}
this.list = new_list //update the old list with the new one
},
get_random_number() { //returns a random number from 0 to 3
return Math.floor(Math.random() * 4)
}
randomise: function() { let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = this.list[randomIndex];
Vue.set(this.list,randomIndex,this.list[i])
this.list[randomIndex] = this.list[i];
this.list[i] = itemAtIndex;
} this.list = input;
}
Array change detection is a bit tricky in Vue. Most of the in place
array methods are working as expected (i.e. doing a splice in your
$data.names array would work), but assigining values directly (i.e.
$data.names[0] = 'Joe') would not update the reactively rendered
components. Depending on how you process the server side results you
might need to think about these options described in the in vue
documentation: Array Change Detection.
Some ideas to explore:
using the v-bind:key="some_id" to have better using the push to add
new elements using Vue.set(example1.items, indexOfItem, newValue)
(also mentioned by Artokun)
Source
Note that it works but im busy so i cant optimize it, but its a little bit too complicted, i Edit it further tomorrow.
Since Vue.js has some caveats detecting array modification as other answers to this question highlight, you can just make a shallow copy of array before randomazing it:
randomise: function() {
// make shallow copy
let input = this.list.map(function(item) {
return item;
});
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
this.list = input;
}