Sending object to firebase using dynamic key value - reactjs

I have a table component that I am using to display the information from all other components in my app. This means that when I send data I can't use the following:
db.collection(collectionName).add({
key1: val1,
key2: val2,
etc...
})
Because the keys could be different depending on which component is using table. I've thought about doing this with a .map() or forEach going through each key but I keep getting syntax errors.
I originally assumed that I could just send the object new_row but that doesn't seem to work properly.
Here is my table component:
class Table extends Component {
constructor(props){
super(props);
this.state = {
rows: null,
temprows: null,
newrow: null,
parent: this.props.tableComponent
}
}
addRow = function(){
var new_rows = [...this.state.rows];
new_rows.push(this.state.newrow);
var new_row = JSON.parse(JSON.stringify(new_rows[0]));
Object.keys(new_row).forEach(function(index) {
new_row[index] = '';
});
db.collection(collectionNAame).add({
I want to add the data here
})
this.setState({
rows: new_rows,
newrow: new_row
});
}
Is there also a better approach, some other method aside from .add for this specific case?

In db.collection .add method, spread and pass this.state.newrow and in the then block update your state. Also in your addRow function, the new_row should be obtained from state (not new_rows[0]
Like this
class Table extends Component {
constructor(props) {
super(props);
this.state = {
rows: null,
temprows: null,
newrow: {},
parent: this.props.tableComponent
};
}
addRow = function() {
var new_rows = [...this.state.rows];
new_rows.push(this.state.newrow);
// var new_row = JSON.parse(JSON.stringify(new_rows[0]));
var new_row = { ...this.state.newrow };
db.collection(collectionNAame)
.add({
...this.state.new_row
})
.then(() => {
Object.keys(new_row).forEach(function(index) {
new_row[index] = "";
});
this.setState({
rows: new_rows,
newrow: new_row
});
});
};
}

Related

setState not returned from render when using Axios

I'm using axios to get data from an endpoint. I'm trying to store this data inside the state of my React component, but I keep getting this error:
Error: Results(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
I've struggled with many approaches: arrow functions etc., but without luck.
export default class Map extends Component {
constructor() {
super();
this.state = {
fillColor: {},
selectedCounty: "",
dbResponse: null,
};
}
getCounty(e) {
axios.get("/getWeatherData?county=" + e.target.id)
.then((response) => {
this.setState(prevState => {
let fillColor = {...prevState.fillColor};
fillColor[prevState.selectedCounty] = '#81AC8B';
fillColor[e.target.id] = '#425957';
const selectedCounty = e.target.id;
const dbResponse = response.data;
return { dbResponse, selectedCounty, fillColor };
})
}).catch((error) => {
console.log('Could not connect to the backend');
console.log(error)
});
}
render() {
return (
<div id="map">
<svg>big svg file</svg>
{this.state.selectedCounty ? <Results/> : null}
</div>
)
}
I need to set the state using prevState in order to update the fillColor dictionary.
Should this be expected? Is there a workaround?

react can not show console log variable

why my log not showing anything ? is ths because the variable isLoading state ?
my code :
function getColumns(data) {
const columns = [];
const sample = data[0];
console.log("theSample" + sample);
and i call it from here :
class App extends React.Component {
constructor() {
super();
this.state = { isLoading: true };
if (this.state.isLoading === false) {
//const data = getData();
const data = this.state.dataExt;
// console.log(data);
const columns = getColumns(data);
this.state = {
data,
columns,
visible: false
};
}
}
Because, you only call getColumns when this.state.isLoading === false, and the initial value of your isLoading state is true. Therefore, unless you update your isLoading state, getColumns wouldn't be called and your log wouldn't show up.

How to use a method in render reactjs?

i have a method set_data which is used to set data based on id. I know it could be easy to call this set_data in componentdidupdate when id changes. However in doing so it doesnt set some state variables in the parent component.
To get rid of that want to call set_data method in render . However since this set_data method sets state of data it enters into an infinite loop in render . Also cannot provide a condition (like prevprops.id!== this.props.id) to execute set_data method.
To prevent it thought of using this set_data method not to set state at all. and can call this set_data method in render.
Below is the code,
export default class child extends React.Component {
state = {
query: '',
data: null,
};
empty_id = 0xffffffff;
componentDidMount() {
this.set_open_data();
}
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
this.set_data();
}
}
set_data = () => {
if (!this.props.info) {
return;
}
if (this.props.id === this.empty_id) {
this.setState({data: null});
return;
}
let data = {
info: [],
values: [],
};
const info = this.props.info;
for (let i=0, ii=info.length; i < ii; i++) {
if (info[i].meshes.includes(this.props.id)) {
const info = info[i].info;
const values = info[i].values;
data = {
info: typeof info === 'string' ? info.split('\r\n') : [],
values: values ? values : [],
};
break;
}
}
this.setState({data: this.filter_data(data, this.state.query)});
};
render = () => {
const shown_data= this.state.data;
/* i want to call set_data method here*/};}
Could someone help me solve this. Thanks.
You can't call setData there, because that would be anti-pattern. It will trigger a loop that will continuously render as well as keeps setting state.
You can probably rewrite the component this way:
export default class child extends React.Component {
state = {
query: ''
};
empty_id = 0xffffffff;
componentDidMount() {
this.set_open_data();
}
set_data = () => {
let data = {};
if (!this.props.info) {
return data;
}
if (this.props.id === this.empty_id) {
return data;
}
let data = {
info: [],
values: [],
};
const info = this.props.info;
for (let i=0, ii=info.length; i < ii; i++) {
if (info[i].meshes.includes(this.props.id)) {
const info = info[i].info;
const values = info[i].values;
data = {
info: typeof info === 'string' ? info.split('\r\n') : [],
values: values ? values : [],
};
break;
}
}
data = this.filter_data(data, this.state.query);
return data;
};
render = () => {
const shown_data= this.state.data;
const data = this.set_data();
/* i want to call set_data method here*/};}
In this, we are not setting data in the state. For every new ID, it will get new data and will compute it from render thereby avoiding antipattern. I have also removed componentDidMount, since we are doing computation in render. Note: This solution means taking away data from the state, if you are not using data anywhere before render, this will work.
Let me know if this helps.

How to fill picker in react native from array

i want to fill a picker items from array .. this array store data from local storage and i want to display this data on picker
this is my function that retrieve data from local storage
async getElementsInLocalStorage() {
try{
let x = [];
let all_keys = await AsyncStorage.getAllKeys();
for(i = 1; i <= all_keys.length;i++ ){
let converter = JSON.parse(await AsyncStorage.getItem('one_person'+i));
x[i] = converter.first_name + ' ' + converter.last_name;
}
this.setState({all_options: x, data: x,});
} catch(error){
alert(error)
}
}
And this is my constructor
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
};
data = [];
}
And this is my Picker
<Picker selectedValue = {this.state.selected} >
{this.state.data.map((value)=><Picker.Item label={value} value={value}/>)}
</Picker>
when type data only in picker picker not filled but when type this.state.data
this is error return
You have defined data as a seperate variable in constructor. But after fetching data you are considering data as a state variable.
Just declare data inside state, and that might solve your issue.
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
data:[]
};
}
Can you try this. What I did is
Moved data inside state and added conditional check before doing .map
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
data = []
};
}
And this is my Picker
<Picker selectedValue = {this.state.selected} >
{this.state.data && this.state.data.map(value=> (<Picker.Item label={value} value={value}/>))}
</Picker>

Loading data from Firebase with React

I have a firebase location with a list of patients
I am trying to reference this location and save it in the state of my react component to later pass to a drop down. I am pretty new to REACT, so i am not sure if this is this best way to this.
import * as firebase from "firebase";
class App extends Component {
constructor() {
super();
this.state = {
patient: []
};
}
componentDidMount() {
let patientList = "";
var rootRef = firebase
.database()
.ref()
.child("patient");
rootRef.on("child_added", snap => {
this.setState({
patient: snap.val().label
});
});
}
render() {
return (
<React.Fragment>
<li>{this.state.patient}</li>
</React.Fragment>
);
}
}
However this code is returning only the last label in the firebase location. Please help.
Try this one
rootRef.on("child_added", snap => {
// Store all the labels in array
var patients = [];
snapshot.forEach(function(snap){
var row = snap.val();
patients.push(row.label);
});
// Store label array into state
this.setState({
patient: patients
});
});
I think this will help your case to implement the real time patient list.
rootRef.on("child_added", snap => {
var patients = this.state.patient || [];
snapshot.forEach(snap => {
var row = snap.val();
patients.push(row.label);
});
this.setState({
patient: patients
});
I hope it helps. Thanks!!

Resources