I use react-native react-native-sqlite-storage in my project and I am struggling to insert data
I managed to successfully read the pre populated table I created in
./android/app/src/main/assets/Mydb.db
but the INSERT statement somehow does not work.
simplified sample code:
import React, { Component } from 'react';
import SQLite from 'react-native-sqlite-storage';
let db;
class App extends Component {
constructor(props) {
// SQLite connection / config settings
db = SQLite.openDatabase({ name: 'testTable', //Name of my table
createFromLocation: "~MyDB.db", // Name of my DB
});
}
selectExample = () => { // working
db.transaction((tx) => {
tx.executeSql('SELECT * FROM testTable', [], (tx, results) => {
console.log("Query completed");
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
console.log(`My AWG: ${row.AWG}, My Metric: ${row.metric}`);
}
});
});
}
updateDatabase = () => { // not working
db.transaction((tx) => {
tx.executeSql('Insert into testTable (AWG, metric) VALUES (?,?)',
[28,0.5],
(tx,results) => {
console.log("Results", results.rowsAffected);
},(err) => {
console.error(err);
}
)
})
}
onPress = () => {
this.selectExample(); // working
this.updateDatabase(); // issue
}
render() {
return (
<View>
<TouchableOpacity style = {styles.button} onPress={() => this.onPress() } />
</View>
);
}
in the console I get Results 1 as feedback, so the query seems fine but when I open MyDB.db with the mac app: DB Browser for SQLite, no changes happened no new rows..
Am I missing something here?
Related
I'm trying to use SQLite in my react-native project.
This is my sample code. I can open my database, but can't bring data from db.
Some people said SQLite does not work for SDK version 30. Maybe this is the problem
result
My code:
SQLite.DEBUG(true);
SQLite.enablePromise(true);
let db;
openDB = ()=>{SQLite.openDatabase(
{
name: 'recipe.db',
createFromLocation: 1,
},
(DB) => {
console.log('success opening recipe.db')
db = DB;
db.transaction((tx) => {
tx.executeSql(`SELECT * FROM recipe;`, [], (tx, results) => {
const rows = results.rows;
for (let i=0; i<rows.length; i++) {
console.log(rows.item(i));
}
})
})
},
error => {
console.error(error);
}
);
}
Thank you for reading!
I am learning how to use GAS now,
I can't delete the specific row I selected on google spread sheet.
I got the theme error after trying to delete using "axios.delete method" when I used react app and google script api.
I already passed GET method and POST method using axios. Actually , I could get and post my data from my google spread sheet.
but deleting could not access well.
I found this error 405 is not allowed to access my google sheet, but Why can I get this error even though the post method was accessible?
My App script or My react.js code need to have any code else ? I can't solve this problem...
I want to solve this error and delete the specific row I selected. Also, I want to know a workaround for this error.
Do you have any idea ? If you have some good idea,Could you tell me please ?
Thank you for reading.
this is my App script code.
function doDelete(req, sheet) {
var id = req.parameter.id;
var Row = sheet.getLastRow();
for (var i = 1; i <= Row; i++) {
var idTemp = sheet.getRange(i, 1).getValue();
if (idTemp == id) {
sheet.deleteRow(i);
}
}
}
this is my reactjs code.
import React,{ useState , Component } from 'react';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:3000';
var optionAxios = {
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Access-Control-Allow-Origin':'*' ,
}
}
const api = 'https://mygoogleappscriptapi.com/exec';
class Price extends Component {
constructor(){
super();
this.state = {
info: []
};
this.getInfo();
this.createInfo = this.createInfo.bind(this);
this.deleteInfo = this.deleteInfo.bind(this);
};
// accessed get!
getInfo = () =>{
axios.get(api)
.then((res) =>{
console.log(res.data)
this.setState({
info: res.data
})
})
}
// accessed post!
createInfo = () =>{
axios.post(api,{
product: "hoge",
price: 1000,
miniLot: 1000,
cartonSize: "40*30*50"
},optionAxios)
.then((res) => {
this.getInfo(res);
})
}
// cant't access delete!
deleteInfo = (e) => {
console.log(e);
axios.delete(api,{
id: e,
},optionAxios)
.then((res) =>{
this.getInfo(res);
console.log('success!');
})
}
render(){
return (
<div className={this.root}>
<Grid container>
<Grid item xs={11}>
<button onClick={this.createInfo}>createButon</button>
<Paper>
{this.state.info.map(info => <div key={info.id}>
{info.product}
<button onClick={() => this.deleteInfo(info.id)}>×</button>
</div>)}
</Paper>
</Grid>
</Grid>
</div>
);
}
}
export default Price;
Only the following HTTP methods are supported:
POST
GET
DELETE method is not supported by google-apps-script-web-application.
You can use post:
Server side:
function doPost(e){
if(e.parameter.option === "DELETE") return doDelete(e);
/*rest of doPost here*/
}
React:
// convert to axios.post
deleteInfo = (e) => {
console.log(e);
axios.post(api,{//modified
id: e,
option: "DELETE",//added
},optionAxios)
.then((res) =>{
this.getInfo(res);
console.log('success!');
})
}
Try this:
function doDelete(req, sh) {
var id = req.parameter.id;
const ss=SpreadsheetApp.getActive();
sh=sh||ss.getActiveSheet();
var vs=sh.getRange(1,1,sh.getLastRow(),1).getValues();
var d=0;
for (var i=0;i<vs.length;i++) {
if (vs[i][0]== id) {
sh.deleteRow(i+1-d++);
}
}
}
I am new to React-Native and I was following the steps on the react-native-sqlite-storage on GitHub but I am unfortunately stuck on the transaction and I've tried enablePromises but it still doesn't work. I am kind of at loss on how to proceed.
import React from 'react';
import SQLite from 'react-native-sqlite-storage';
import { StyleSheet, Text, View, ListItem } from 'react-native';
export default function App() {
let db = SQLite.openDatabase(
{
name: 'users',
createFromLocation: 1,
},
successToOpenDB(),
failToOpenDB()
);
function successToOpenDB() {
db.transaction((tx) => {
tx.executeSql('SELECT * FROM USERS', [], (tx, results) => {
let dataLength = results.row.length;
alert(dataLength);
});
});
}
function failToOpenDB(err) {
console.log(err);
}
return (
<>
<View style={styles.header}>
<Text style={styles.headerText}>Title</Text>
</View>
</>
);
};
Thanks!
You are passing the success callback successToOpenDB function while making a connection to db and using "db" which is undedined and u are getting error "cannot read property transaction of undefined.So do not pass successToOpenDB funtion as a success callback.
errorCB(err) {
console.log("SQL Error: " + err);
},
successCB() {
console.log("SQL executed fine");
},
openCB() {
console.log("Database OPENED");
},
var db = SQLite.openDatabase({
name: 'users',
createFromLocation: 1,
}, openCB, errorCB);
db.transaction((tx) => {
tx.executeSql('SELECT * FROM Employees a, Departments b WHERE a.department = b.department_id', [], (tx, results) => {
console.log("Query completed");
// Get rows with Web SQL Database spec compliance.
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`);
}
// Alternatively, you can use the non-standard raw method.
/*
let rows = results.rows.raw(); // shallow copy of rows Array
rows.map(row => console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`));
*/
});
});
I'm messing with ag-grid, react-apollo, and everything seems to be working fine. The goal here is to click a check box and have a mutation / network request occur modifying some data. The issue i'm having is that it redraws the entire row which can be really slow but im really just trying to update the cell itself so its quick and the user experience is better. One thought i had was to do a optimistic update and just update my cache / utilize my cache. What are some approach you guys have taken.
Both the columns and row data are grabbed via a apollo query.
Heres some code:
CheckboxRenderer
import React, { Component } from "react";
import Checkbox from "#material-ui/core/Checkbox";
import _ from "lodash";
class CheckboxItem extends Component {
constructor(props) {
super(props);
this.state = {
value: false
};
this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
}
componentDidMount() {
this.setDefaultState();
}
setDefaultState() {
const { data, colDef, api } = this.props;
const { externalData } = api;
if (externalData && externalData.length > 0) {
if (_.find(data.roles, _.matchesProperty("name", colDef.headerName))) {
this.setState({
value: true
});
}
}
}
updateGridAssociation(checked) {
const { data, colDef } = this.props;
// const { externalData, entitySpec, fieldSpec } = this.props.api;
// console.log(data);
// console.log(colDef);
if (checked) {
this.props.api.assign(data.id, colDef.id);
return;
}
this.props.api.unassign(data.id, colDef.id);
return;
}
handleCheckboxChange(event) {
const checked = !this.state.value;
this.updateGridAssociation(checked);
this.setState({ value: checked });
}
render() {
return (
<Checkbox
checked={this.state.value}
onChange={this.handleCheckboxChange}
/>
);
}
}
export default CheckboxItem;
Grid itself:
import React, { Component } from "react";
import { graphql, compose } from "react-apollo";
import gql from "graphql-tag";
import Grid from "#material-ui/core/Grid";
import _ from "lodash";
import { AgGridReact } from "ag-grid-react";
import { CheckboxItem } from "../Grid";
import "ag-grid/dist/styles/ag-grid.css";
import "ag-grid/dist/styles/ag-theme-material.css";
class UserRole extends Component {
constructor(props) {
super(props);
this.api = null;
}
generateColumns = roles => {
const columns = [];
const initialColumn = {
headerName: "User Email",
editable: false,
field: "email"
};
columns.push(initialColumn);
_.forEach(roles, role => {
const roleColumn = {
headerName: role.name,
editable: false,
cellRendererFramework: CheckboxItem,
id: role.id,
suppressMenu: true,
suppressSorting: true
};
columns.push(roleColumn);
});
if (this.api.setColumnDefs && roles) {
this.api.setColumnDefs(columns);
}
return columns;
};
onGridReady = params => {
this.api = params.api;
this.columnApi = params.columnApi;
this.api.assign = (userId, roleId) => {
this.props.assignRole({
variables: { userId, roleId },
refetchQueries: () => ["allUserRoles", "isAuthenticated"]
});
};
this.api.unassign = (userId, roleId) => {
this.props.unassignRole({
variables: { userId, roleId },
refetchQueries: () => ["allUserRoles", "isAuthenticated"]
});
};
params.api.sizeColumnsToFit();
};
onGridSizeChanged = params => {
const gridWidth = document.getElementById("grid-wrapper").offsetWidth;
const columnsToShow = [];
const columnsToHide = [];
let totalColsWidth = 0;
const allColumns = params.columnApi.getAllColumns();
for (let i = 0; i < allColumns.length; i++) {
const column = allColumns[i];
totalColsWidth += column.getMinWidth();
if (totalColsWidth > gridWidth) {
columnsToHide.push(column.colId);
} else {
columnsToShow.push(column.colId);
}
}
params.columnApi.setColumnsVisible(columnsToShow, true);
params.columnApi.setColumnsVisible(columnsToHide, false);
params.api.sizeColumnsToFit();
};
onCellValueChanged = params => {};
render() {
console.log(this.props);
const { users, roles } = this.props.userRoles;
if (this.api) {
this.api.setColumnDefs(this.generateColumns(roles));
this.api.sizeColumnsToFit();
this.api.externalData = roles;
this.api.setRowData(_.cloneDeep(users));
}
return (
<Grid
item
xs={12}
sm={12}
className="ag-theme-material"
style={{
height: "80vh",
width: "100vh"
}}
>
<AgGridReact
onGridReady={this.onGridReady}
onGridSizeChanged={this.onGridSizeChanged}
columnDefs={[]}
enableSorting
pagination
paginationAutoPageSize
enableFilter
enableCellChangeFlash
rowData={_.cloneDeep(users)}
deltaRowDataMode={true}
getRowNodeId={data => data.id}
onCellValueChanged={this.onCellValueChanged}
/>
</Grid>
);
}
}
const userRolesQuery = gql`
query allUserRoles {
users {
id
email
roles {
id
name
}
}
roles {
id
name
}
}
`;
const unassignRole = gql`
mutation($userId: String!, $roleId: String!) {
unassignUserRole(userId: $userId, roleId: $roleId) {
id
email
roles {
id
name
}
}
}
`;
const assignRole = gql`
mutation($userId: String!, $roleId: String!) {
assignUserRole(userId: $userId, roleId: $roleId) {
id
email
roles {
id
name
}
}
}
`;
export default compose(
graphql(userRolesQuery, {
name: "userRoles",
options: { fetchPolicy: "cache-and-network" }
}),
graphql(unassignRole, {
name: "unassignRole"
}),
graphql(assignRole, {
name: "assignRole"
})
)(UserRole);
I don't know ag-grid but ... in this case making requests results in entire grid (UserRole component) redraw.
This is normal when you pass actions (to childs) affecting entire parent state (new data arrived in props => redraw).
You can avoid this by shouldComponentUpdate() - f.e. redraw only if rows amount changes.
But there is another problem - you're making optimistic changes (change checkbox state) - what if mutation fails? You have to handle apollo error and force redraw of entire grid - change was local (cell). This can be done f.e. by setting flag (using setState) and additional condition in shouldComponentUpdate.
The best way for me to deal with this was to do a shouldComponentUpdate with network statuses in apollo, which took some digging around to see what was happening:
/**
* Important to understand that we use network statuses given to us by apollo to take over, if either are 4 (refetch) we hack around it by not updating
* IF the statuses are also equal it indicates some sort of refetching is trying to take place
* #param {obj} nextProps [Next props passed into react lifecycle]
* #return {[boolean]} [true if should update, else its false to not]
*/
shouldComponentUpdate = nextProps => {
const prevNetStatus = this.props.userRoles.networkStatus;
const netStatus = nextProps.userRoles.networkStatus;
const error = nextProps.userRoles.networkStatus === 8;
if (error) {
return true;
}
return (
prevNetStatus !== netStatus && prevNetStatus !== 4 && netStatus !== 4
);
};
It basically says if there is a error, just rerender to be accurate (and i think this ok assuming that errors wont happen much but you never know) then I check to see if any of the network statuses are not 4 (refetch) if they are I dont want a rerender, let me do what I want without react interfering at that level. (Like updating a child component).
prevNetStatus !== netStatus
This part of the code is just saying I want the initial load only to cause a UI update. I believe it works from loading -> success as a network status and then if you refetch from success -> refetch -> success or something of that nature.
Essentially I just looked in my props for the query and saw what I could work with.
I have set up a call to fetch data from my firebase database using react native.
Database structure
Code inside FirebaseList.js
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentWillMount() {
firebase.database().ref('/signposts/items').on('value', snapshot => {
const dataArray = [];
const result = snapshot.val();
for (const data in result) {
dataArray.push(data);
}
this.setState({ data: dataArray });
console.log(this.state.data);
});
}
render() {
return (
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<Text>{item}</Text>
)}
keyExtractor={item => item}
/>
);
}
I believe the connection to firebase is successful as I can build and run the application. However, when the component renders, I do not see my two rows of data 'row1' and 'row2'.
You said your code is right then also check that this rules are set
{
"rules": {
"foo": {
".read": true,
".write": false
}
}
}
Note : - When you use the above rule your database is open for all Read more here. Make you use update the rules once you push to production.
If console.log(dataArray) shows an empty array (assuming that console.log() works...), try checking your connection:
componentDidMount() {
const ref = firebase.database().ref('/signposts');
const checkConnection = firebase.database().ref(`.info/connected`);
checkConnection.on('value', function(snapshot) {
if (snapshot.val() === true) { /* we're connected! */
firebase.database().ref('/signposts').on('value', snapshot => {
const dataArray = [];
const result = snapshot.val();
for (const data in result) {
dataArray.push(data);
}
if (dataArray.length === 0)
console.log("No data.")
else
this.setState({ listViewData: dataArray });
});
} else { /* we're disconnected! */
console.error("Check your internet connection.")
}
}
}