Waiting Before Writing to Database - mysql

I have a giant form, and it's setup so that the handleChange method changes the state values of the data as the user types. I then want it to write to the mySql database, which I can also do, except currently, it writes after every keypress. I'm trying to figure out how to wait a few seconds after input stops, so that it doesn't do it after every single key press.
handleChange(e) {
const targetName = e.target.name;
const targetValue = e.target.value
this.setState({
[e.target.name]: e.target.value
});
console.log(`${targetName}: ${targetValue}`);
/// I want a timer here that will only move on if input has stopped for a few seconds.
/// Call to my database query will be here
}

For anyone who wants the answer that I used, I put it together from the link that #WilTree posted above.
let timeout;
class General extends Component {
constructor(props) {
super(props);
this.state = {
typing: false,
typingTimeout: 0,
organization: "",
address: "",
website: "",
industry: "",
status: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
const targetName = e.target.name;
const targetValue = e.target.value
this.setState({
[e.target.name]: e.target.value
});
if (this.state.typingTimeout) {
clearTimeout(this.state.typingTimeout);
}
this.setState({
typing: false,
typingTimeout: setTimeout(function () {
console.log(`${targetName}: ${targetValue}`);
}, 3000)
});
}

Related

How do I pass the data from one React.js file to another?

I'd like to pass data from App.js to another .js file within React. Atm, I'm reading and writing from local storage between files but this seems inefficient. I'd like to only pull from local storage once when the App.js component mounts. This is what I'm doing currently.
App.js:
constructor(props) {
super(props);
this.state = {
user: {},
user_data: (localStorage.getItem('user_data')),
}
this.authListener = this.authListener.bind(this);
}
componentDidMount() {
this.authListener();
}
//checks firebase for authentication
authListener() {
Authentication.auth().onAuthStateChanged((user) => {
console.log(user);
if (user) {
this.setState({ user });
localStorage.setItem('user', user.uid);
this.pulldata_Health();
this.pulldata_Meals();
this.pulldata_Ingredients();
} else {
this.setState({ user: null })
localStorage.removeItem('user');
localStorage.removeItem('user_data')
}
});
}
//connects to database and stores data to local storage
pulldata_Health() {
database.collection('Health_data')
.doc(localStorage.getItem('user'))
.get()
.then(doc => {
const data = doc.data();
localStorage.setItem('user_data', JSON.stringify(data));
console.log(JSON.parse(localStorage.getItem('user_data')))
}).catch(function (error) {
console.error("Error reading health", error);
});
Homepage.js:
constructor(props) {
super(props);
this.state = {
healthData: (JSON.parse(localStorage.getItem('user_data')))
}
}
componentDidMount() {
this.GoalChecker();
console.log(this.state.healthData);
}
GoalChecker() {
if (this.state.healthData !== null) {
if (this.state.healthData.goal === 'Gain') {
this.setState({ gainImage: true });
this.setState({ recompImage: false });
this.setState({ loseImage: false });
console.log('gainimg')
}
if (this.state.healthData.goal === 'Recomp') {
this.setState({ gainImage: false });
this.setState({ recompImage: true });
this.setState({ loseImage: false });
console.log('recompimg')
}
if (this.state.healthData.goal === 'Lose') {
this.setState({ gainImage: false });
this.setState({ recompImage: false });
this.setState({ loseImage: true });
console.log('loseimg')
}
}
};
This all works, but pulling from local storage every time this page loads seems a bit inefficient. Is there any way to push the props of User data from App.js to my other page?
It is very difficult for me to explain, but i'll show you a video from YouTube how to do this with react-hooks. It is not a very difficult method
https://youtu.be/XuFDcZABiDQ
YOu can use react context. Create a context within app.js/at the top of your application. Wrap the top-level container using a context component. Within any child components, you can then access props in the global context.
A great tutorial that explains it is here, https://kentcdodds.com/blog/how-to-use-react-context-effectively

Gatsby/Axios: Trying to use js-search, axios doesnt use given JSON-response

The code trying to fetch data:
class Search extends Component {
state = {
bookList: [],
bookk: "",
search: [],
searchResults: [],
isLoading: true,
isError: false,
searchQuery: "",
}
/**
* React lifecycle method to fetch the data
*/
async componentDidMount() {
Axios.get('http://localhost:8000/hentObjekterJSON/Studium')
.then(result => {
const bookData = result.data
bookk = result.data
this.setState({ bookList: bookData.Studium})
this.rebuildIndex()
})
.catch(err => {
this.setState({ isError: true })
console.log("====================================")
console.log(`Something bad happened while fetching the data\n${err}`)
console.log("====================================")
})
}
The JSON-Response:
{"Studium": {"studiumkode": "ABIOK", "studium": "ABIOK (anestesi/barnevern/intensiv/operasjon/kreftsykepleie"}}
Neither bookList nor bookk seems to have data assigned at all.
I have checked and the URL is serving the JSON (as a JsonResponse))
Why won't Axios find and use the data?
Some suggested pointers...
class Search extends Component {
state = {
bookList: [],
bookk: "",
search: [],
searchResults: [],
isLoading: true,
isError: false,
searchQuery: "",
}
/**
* React lifecycle method to fetch the data
*/
// Not sure you need async on the below line
async componentDidMount() {
Axios.get('http://localhost:8000/hentObjekterJSON/Studium')
.then(result => {
const bookData = result.data
console.log(bookData) // Actually see what is returned.
// You may need to parse the data....
const bookData = JSON.parse(result.data)
bookk = result.data // This should a 'setState'.
this.setState({ bookList: bookData.Studium,
bookk: result.data})
// setState is async, so rebuild might run before setState has finished.
this.rebuildIndex()
// If you want something to run only once set state has completed, then try
this.setState({ bookList: bookData.Studium,
bookk: result.data}, this.rebuildIndex())
})
.catch(err => {
this.setState({ isError: true })
console.log("====================================")
console.log(`Something bad happened while fetching the data\n${err}`)
console.log("====================================")
})
}

What's the best way to mock a nested function?

consider a function
exports.projectNotifyLaunch = (admin, functions) => {
return functions.database.ref("/projects/{pid}").onCreate(snap => {
const { title } = snap.val();
const notification = {
title: `${title} just launched!`,
body: `We just heard about a new cryptocurrency project called ${title}`
};
return admin.messaging().sendToTopic("premium", { notification });
});
};
How should I mock deeply nested functions such as
functions.database.ref("/projects/{pid}").onCreate(snap => {});
or
admin.messaging().sendToTopic("premium", { notification });
in Jest? I want to fire off the snap=>{} callback and assert against the value of notification.
I was able to make this work
This works but it's quite verbose. I'm wondering if there is a better way, or a type of testing I'm not aware of with Jest.
describe("send notification to premium users on new project", () => {
// INPUTS
const snap = {
val: () => ({
title: "Test Title"
})
};
const functions = {
database: {
ref: () => ({
onCreate: callback => callback(snap)
})
}
};
// outputs
let topicStub = null;
let notificationStub = null;
const admin = {
messaging: () => ({
sendToTopic: (topic, notification) => {
topicStub = topic;
notificationStub = notification;
}
})
};
projectNotifyLaunch(admin, functions);
test("title is correct", () => {
expect(notificationStub.notification.title).toBe(
"Test Title just launched!"
);
});
test("topic is premium", () => {
expect(topicStub).toBe("premium");
});
});

How can I properly read json data from ajax response?

I did something like this:
axios.get(url).then(result => {
this.setState({
list: result.data,
});
})
.catch(e => {
console.log("Some error", e);
});
Constructor looks like this:
constructor(props: any) {
super(props);
this.state = {
list: [],
};
}
I want to put it somewhere and check whether it works:
const {fetchedData}: any = this.state;
const data: IScheduler = fetchedData.list;
but I get uncaught TypeError: cannot read property 'list' of undefined...
It works when I do that this way:
const data: IScheduler = {
generatedDate: "03.12.2017";
subjects: [
....
],
};
But it's not the point. What am I doing wrong? How should I fix it? Can somebody help me?
In your state there is no property fetchedData. You set your list to this.state.list, not to this.state.fetchedData.list. So you need to change your code from:
const {fetchedData}: any = this.state;
const data: IScheduler = fetchedData.list;
to:
const {list}: any = this.state;
const data: IScheduler = list;
It should work. If you really want your first data structure you need to change your default state structure and setState, but nested data structure is not recommended.
axios.get(url).then(result => {
this.setState({
fetchedData: {
list: result.data
}
});
})
.catch(e => {
console.log("Some error", e);
});
Constructor should looks like this:
constructor(props: any) {
super(props);
this.state = {
fetchedData: {
list: []
}
};
}

How to know when the feathers-client is connected to a service

I'm trying to test an event filter however there's a timing issue that I'm not sure how to resolve. Other than wrapping the REST request in a setTimeout, how could I get this working?
const app = require('../../src/app');
const feathers = require('feathers/client')
const socketio = require('feathers-socketio/client');
const hooks = require('feathers-hooks');
const io = require('socket.io-client');
const rp = require('request-promise');
const service = app.service('users');
let server = null;
describe('\'users\' service', () => {
beforeEach((done) => {
server = app.listen('3030');
server.once('listening', done);
});
afterEach((done) => {
server.close(done);
});
it('returns stuff #test', (done) => {
const socket = io('http://localhost:3030');
const app = feathers()
.configure(hooks())
.configure(socketio(socket));
const messageService = app.service('users');
messageService.on('created', message => {
console.log('Created a message', message);
done();
});
socket.on('connection', () => {
//
// The messageService is not connected yet
// so messages.filters.js will not fire
//
// Giving it a chance to connect with setTimeout does work...
// setTimeout(() => {
rp({
method: 'POST',
url: 'http://localhost:3030/users',
body: {
test: 'Message from REST'
},
json: true
});
// }, 500);
});
});
});
I have tried replacing the socket.on with these as well:
messageService.on('connection'
service.on('connection' (based on Node.js EventEmitter)
and so on...
Edit
I have since found service.on('newListener' works however it is being triggered many times. I need to track down the single connection:
const messageService = app.service('users');
messageService.on('created', message => {
console.log('Created a message', message);
done();
});
It's simply service.on('newListener'.
https://nodejs.org/api/events.html#events_event_newlistener
Listeners registered for the 'newListener' event will be passed the event name and a reference to the listener being added.
However, when I implemented this I found that it is listening to 5 different events. So, you need to filter those down:
service.on('newListener', (event, listener) => {
if (event === 'created') {
rp({
method: 'POST',
url: 'http://localhost:3030/users',
body: {
test: 'Message from REST'
},
json: true
});
}
});