google autocomplete places api in react - reactjs

I'm using google places autocomplete api in my react code.When i kept this code in seperate file and was calling this component in another it was working properly.But when i combined place search input feild with others field in form its not working.Whats the issue when i combined with other field in form?
This code
import React from "react";
/* global google */
class SearchBar extends React.Component {
constructor(props) {
super(props);
this.autocompleteInput = React.createRef();
this.autocomplete = null;
this.handlePlaceChanged = this.handlePlaceChanged.bind(this);}
componentDidMount() {
this.autocomplete = new google.maps.places.Autocomplete(this.autocompleteInput.current,
{"types": ["geocode"]});
this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
}
handlePlaceChanged(){
const place = this.autocomplete.getPlace();
this.props.onPlaceLoaded(place);
}
render() {
return (
<input ref={this.autocompleteInput} id="autocomplete" placeholder="Enter your address"
type="text"></input>
);
}
}
output of this:
in seperate file
code after integrating other files(form input)
import React from "react";
import Geocode from "react-geocode";
import DatePicker from 'react-datepicker';
import Scrollbars from 'react-custom-scrollbars';
require('react-datepicker/dist/react-datepicker.css');
// set Google Maps Geocoding API for purposes of quota management. Its optional but
recommended.
Geocode.setApiKey("API_KEY");
/* global google */
export default class Checkout extends React.Component {
constructor(props) {
super(props);
this.state = {
locality: "",
lat : 0,
lng: 0,
otherState...
}
this.autocompleteInput = React.createRef();
this.autocomplete = null;
this.handlePlaceChanged = this.handlePlaceChanged.bind(this);
}
componentDidMount() {
this.autocomplete = new google.maps.places.Autocomplete(this.autocompleteInput.current,
{"types": ["geocode"]});
this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
}
handlePlaceChanged(){
const place = this.autocomplete.getPlace().formatted_address;
//this.props.onPlaceLoaded(place);
this.setState({locality: place})
Geocode.fromAddress(this.state.locality).then(
response => {
const { lat, lng } = response.results[0].geometry.location;
console.log(lat, lng);
this.setState({
lat: lat,
lng: lng
})
},
error => {
console.error(error);
}
);
}
render() {
let publicUrl = process.env.PUBLIC_URL+'/'
let items = JSON.parse(localStorage.getItem("items"));
return (
// checkout page
<div className="contact-area pd-top-20 pd-bottom-65">
<div className="container">
<form className="contact-form-wrap contact-form-bg" onSubmit={e =>
this.handleSubmit(e)}>
<h4>Checkout</h4>
...other input feilds
<div className="row">
<div className="col-10 col-md-11" >
<h4>Select/Add new address</h4>
<div className="rld-single-input">
<label>Enter new address</label>
<input className="mb-2" ref={this.autocompleteInput} id="autocomplete"
placeholder="Enter Locality"
type="text"></input>
<input placeholder="Enter flat no./Bilding name" onChange={(e) =>
this.handleLandmark(e)}/>
</div>
</div>
</div>
</div>
</form>
Output after adding all code into one file

Accessing this.state immediately after calling this.setState({...}) is not a guaranteed operation because it's asynchronous read this react FAQ.
So what I will advice you do is pass a callback as second argument to this.setState(newState, callback), and your callback should contain the whole body of Geocode.fromAddress(...) while you access your state from inside your callback.

Related

Password show/hide using Eye/EyeSlash in React

I am trying to implement eye/eyeslash in on my Register form in React.
This is a function that's is responsible for changing visibility type and eye icon changing.
import React, { useState } from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
export const usePasswordToggle = () => {
const [visible, setVisibility] = useState();
const Icon = <FontAwesomeIcon icon={visible ? "eye-slash" : "eye"} />;
const InputType = visible ? "text" : "password";
return [InputType, Icon];
};
I am trying to implement it in component responsible for registering.
import React, { Component, createRef } from "react";
import { usePasswordToggle } from "./usePasswordToggle";
class Register1 extends React.Component {
EmailR = createRef();
UsernameR = createRef();
PasswordR = createRef();
PasswordConfirmR = createRef();
constructor(props) {
super();
this.state = {
message: "",
password: "",
confirmPassword: "",
};
}
handleSubmit = (event) => {
// alert(this.PasswordR.current.value);
// alert(this.PasswordConfirmR.current.value);
if (this.PasswordR.current.value !== this.PasswordConfirmR.current.value) {
alert("The passwords doesn't match");
return false; // The form won't submit
} else {
alert("The passwords do match");
return true; // The form will submit
}
};
onCreateAccount = () => {
let loginInfo = {
Username: this.UsernameR.current.value,
Email: this.EmailR.current.value,
Password: this.PasswordR.current.value,
};
fetch("http://localhost:5000/api/authenticate/register", {
method: "POST",
headers: { "Content-type": "application/json" },
body: JSON.stringify(loginInfo),
})
.then((r) => r.json())
.then((res) => {
if (res) {
this.setState({
message:
"New Account is Created Successfully. Check your email to verify Account.",
});
}
});
};
render() {
return (
<div>
<h2 className="FormDescription">
{" "}
Please enter Account details for registration
</h2>
<div className="Form">
<p>
<label>
Email: <input type="text" ref={this.EmailR} />
</label>
</p>
<p>
<label>
Username: <input type="text" ref={this.UsernameR} />
</label>
</p>
<div>
<label>
Password:{" "}
<input type={usePasswordToggle.InputType} ref={this.PasswordR} />
</label>
<span className="password-toogle-icon">
{usePasswordToggle.Icon}
</span>
</div>
<p>
<label>
ReenterPassword:{" "}
<input type="password" ref={this.PasswordConfirmR} />{" "}
</label>
</p>
<button onClick={this.handleSubmit}> Create </button>
<p>{this.state.message}</p>
</div>
</div>
);
}
}
export default Register1;
My password is always visible, and eye icon is even not visible on the form (it should be inside my input field, but it is not).
Focus on this code snippet:
<div>
<label>
Password: <input type={usePasswordToggle.InputType} ref={this.PasswordR} />
</label>
<span className="password-toogle-icon">{usePasswordToggle.Icon}</span>
</div>
Any suggestion what is the problem?
Change this
const [visible, setVisibility] = useState();
to this
const [visible, setVisible] = useState(true);
as the official documentation here
First, add a default value to your useState, either true or false depending on which icon you want to render first.
Then, you should add a onClick method to your icon which will toggle the visibility state. You're setting the icon based on visible value, but you never toggle the value.
onClick={() => setVisibility(!visible)}
UPDATE
You also need to execute your Hook inside your main component (because yes, you wrote what React call a Hook), like so :
const [inputType, icon] = usePasswordToggle();
But doing so, you'll get an error from React that say you cannot use a Hook within a class component due to how they work.
Basically you need to change your Register1 component to be a functional component, and not a class anymore. Look here for a quick overview on how to : https://reactjs.org/docs/components-and-props.html

How to resolve list of objects not rendering

Hello I am new to ReactJS so I am just practising on working with states and also so a good practice for a starting point I thought why not the classic TODO App.
So I do not know why the object is not being rendered or being added because when I even console logged the object It did not even show that it's empty or anything the was literally no output so I do not know where I could have went wrong with this methods
Code Below App.js: This is the file that has all the methods and state control of the TODO APP
import React, { Component } from 'react';
import style from './stylesheet/app.css'
import ListItems from './ListItems'
class App extends Component{
constructor(props){
super(props);
this.state = {
items:[],
currentItem:{
notes: '',
key: ''
}
}
this.handleInput = this.handleInput.bind(this);
this.addItem = this.addItem.bind(this);
}
// Handling user Input to save on before I add to the Items
// this.state.currentItems is a temporary store place for TODO'S
handleInput(e){
this.setState({
currentItem: {
notes: e.target.value,
key: Date.now()
}
})
}
// After handling input input once the add button is clicked I want to add
// the the object in the temporary storage into the permanent store place that is the
// this.state.items --> permanent store place
addItem(e){
e.preventDefault()
const newTodo = this.state.currentItem;
if (newTodo.text !== " "){
const newTodos = [...this.state.items, newTodo];
this.setState({
items:newTodos,
currentItem:{
notes:'',
key:''
}
})
}
}
render(){
return(
<div className="container" style={style}>
<div className='todo-form'>
<form id="form">
<input type="text"
placeholder="Enter in your todo's"
value={this.state.currentItem.notes}
onChange={this.handleInput}></input>
<button type="submit" onSubmit={this.addItem}>Add Todo</button>
</form>
<ListItems items={this.state.items}/>
</div>
</div>
)
}
}
export default App
Code Below ListItems.js: This file contains code where I tried to map through the ojects to display the TODO'S
import React from 'react';
const ListItems = (props) =>{
const items = props.items;
const listItems = items.map(item =>{
return <div className="todo-list" key={item.key}> <p>{item.key}</p> </div>
})
return(
<div>
{listItems}
</div>
)
}
export default ListItems
Can you please help me figure out where I could be going wrong?
Your code works perfectly fine. Just add addItem function to form element, so it preventsDefault correctly and doesnt reload whole page:
<form id="form" onSubmit={this.addItem}>
See here: https://codesandbox.io/s/musing-gareth-vlkmx

delete data in firebase using React application

Good day, I'm new React and firebase, Today, I using React and Firebase to display, add and delete data. I have some data in the firebase and display it. Now, I want delete some of the data, but I don't know. I create a button delete that whenever the user click it the data will be removed. Please help..
import React , { Component, Fragment } from 'react';
class Form extends Component {
constructor(){
super();
this.state = {
db: [],
name: "",
city: ""
}
this.changHandle = this.changHandle.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.removeData = this.removeData.bind(this)
}
componentDidMount() {
const { firestore } = this.props
firestore.collection('cafes').orderBy('name')
.onSnapshot((db) => {
const data = db.docs.map(datas => datas.data())
this.setState({
db: data
})
})
}
changHandle(event){
const {name, value} = event.target
this.setState({[name]:value})
}
handleSubmit(e){
e.preventDefault();
this.props
.firestore
.collection('cafes')
.add({city: this.state.city, name: this.state.name})
}
removeData(id){
this.props
.firestore
.collection('cafes').doc(id).delete();
}
render(){
return (
<div>
<form onSubmit={this.handleSubmit} autoComplete = "off">
<input
type="text"
name="name"
value={this.state.name}
placeholder="Name"
onChange={this.changHandle}
/><br/>
<input
type="text"
name="city"
value={this.state.city}
placeholder="City"
onChange={this.changHandle}
/><br/>
<button type="submit">Add user</button>
</form>
<p>Name:{this.state.name} {this.state.city}</p>
{this.state.db.map(data =>
<div>
<li key={data.id}>{data.name} {data.city}</li>
<button onClick={() => this.removeData(data.id)}>Delete</button>
</div>)
}
</div>
)
}
}
export default Form
MyApplication
The problem is that you are not setting an id for your document in firestore so it is just assigning a random one. In your handle submit button you need to do something like this:
const id = new Date().getTime()
this.props
.firestore
.collection('cafes').doc(id)
.add({city: this.state.city, name: this.state.name, id: id})

React + Firebase – Update the increment state of Like/Clap button to Firebase

Codesandbox: https://codesandbox.io/s/github/adamschwarcz/react-firebase-app
I am really new to react and firebase and I followed this tutorial to come up with this app (full project – github link here) – it's an "Add your Wish app"
My problem is that I cannot store clap count on each post to my firebase – this component is called LikeButton.js.
I have been trying to add some similar firebase code (handleChange, handleSubmit, componentDidMount... etc.. etc..) as I learned in the tutorial to LikeButton.js to store the total amount of counts in firebase each time the button is clicked and the amount of claps incremented by +1.
Simply what I want – everytime the clap button is clicked and the initial ('0') state of count is incremented to +1 the current count is going to be updated into the database.
Just cannot come up with solution, can somebody please help?
My LikeButton.js code without any firebase:
import React, { Component } from 'react'
import firebase from '../../firebase.js';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import './Like.css';
class LikeButton extends Component {
state = {
count: 0,
}
incrementLike = () => {
let newCount = this.state.count + 1
this.setState({
count: newCount
})
console.log(this.state.count);
}
render() {
return(
<div class="counter">
<Button type="submit" color="primary" onChange={this.handleCount} onClick={this.incrementLike}>{this.state.count} 👏</Button>
</div>
)
}
}
export default LikeButton
My Add.js code with firebase:
import React, { Component } from 'react';
import firebase from '../../firebase.js';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField';
import FadeIn from "react-fade-in";
import Placeholder from '../Placeholder/Placeholder.js';
import LikeButton from '../Like/Like.js'
import './Add.css';
class Add extends Component {
constructor() {
super();
this.state = {
loading: true,
currentItem: '',
username: '',
items: []
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
handleSubmit(e) {
e.preventDefault();
const itemsRef = firebase.database().ref('items');
const item = {
title: this.state.currentItem,
user: this.state.username
}
itemsRef.push(item);
this.setState({
currentItem: '',
username: ''
});
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/posts")
.then(response => response.json())
.then(json => {
setTimeout(() => this.setState({ loading: false }), 1500);
});
const itemsRef = firebase.database().ref('items');
itemsRef.on('value', (snapshot) => {
let items = snapshot.val();
let newState = [];
for (let item in items) {
newState.push({
id: item,
title: items[item].title,
user: items[item].user
});
}
this.setState({
items: newState
});
});
}
removeItem(itemId) {
const itemRef = firebase.database().ref(`/items/${itemId}`);
itemRef.remove();
}
render() {
return (
<div className="container">
<div className="wrap">
<section className="add-item">
<h1>Napíš svoj wish</h1>
<h3>Možno prilepíš sebe, možno posunieš firmu.</h3>
<form onSubmit={this.handleSubmit}>
<TextField
id="filled-required"
label="Meno"
name="username"
variant="filled"
value={this.state.username}
onChange={this.handleChange}
/>
<TextField
required
id="standard-multiline-flexible"
label="Tvoje prianie"
name="currentItem"
variant="filled"
multiline
rows="6"
rowsMax="8"
value={this.state.currentItem}
onChange={this.handleChange}
/>
<Button
type="submit"
variant="contained"
color="primary">
Poslať wish
</Button>
</form>
</section>
<section className='items-list'>
<div className="item">
<div>
{this.state.items.map((item) => {
return (
<div>
{this.state.loading ? (
<>
<FadeIn>
<Placeholder />
</FadeIn>
</>
) : (
<div className="wish" key={item.id}>
<FadeIn>
<h2>{item.title}</h2>
<div className="name">
<p>poslal <span>{item.user}</span></p>
<LikeButton />
</div>
</FadeIn>
</div>
)}
</div>
)
})}
</div>
</div>
</section>
</div>
</div>
);
}
}
export default Add
First of all, you need to tell the LikeComponent which Wish it will be updating, and you will also need to be able to access the clapCount of the wish from the LikeComponent. This can be done easily using props. You should re-configure LikeComponent to accept a prop similar to wish, which would be the wish that you are displaying and modifying.
So, this line in Add.js
<LikeButton />
would instead look like <LikeButton wish={item} />. This way, your LikeComponent can access the item/wish.
Next, in the LikeComponent, you need to remove the local state and instead use the clap count stored in Firebase. Luckily, since you're passing the wish via a prop, you can simply refactor the LikeComponent to look like this:
class LikeButton extends Component {
incrementLike = () => {
// TODO: Implement clap incrementation via Firebase updates
}
render() {
return(
<div class="counter">
<Button type="submit" color="primary" onClick={this.incrementLike}>{this.props.wish.clapCount} 👏</Button>
</div>
)
}
}
Next, we need to actually implement incrementLike. Luckily, since we are getting the wish item passed to us via the wish prop, we can easily update it like so:
incrementLike = () => {
// get a reference to the item we will be overwriting
const wishRef = firebase.database().ref(`/items/${this.props.wish.id}`);
// get the current value of the item in the database
wishRef.once('value')
.then(snapshot => {
// get the value of the item. NOTE: this is unsafe if the item
// does not exist
let updatedWish = snapshot.val();
// update the item's desired property to the desired value
updatedWish.clapCount = updatedWish.clapCount + 1;
// replace the item with `wish.id` with the `updatedWish`
wishRef.set(updatedWish);
});
}
While this should work with only a few tweaks, I'm sure there's a better way to do it. You might even be able to avoid the call to once('value') since you're passing wish as a prop to LikeComponent. You should play around with it.
However, I strongly encourage you to explore migrating to Firebase Cloud Firestore. It's API is way more straightforward (in my opinion) than Realtime Database.

Posting data to Mongo database using axios (React front end)

I am re-creating a basic chat from a previous project (formerly used Bootstrap and Socket) and this go around I am utilizng a React component to render the chat (which consists of an input area for user name, an input area for text content, and a div where the username and message inserted should appear together i.e. "BugsBun01: "Whats up Doc?!"). I am unsure whether or not I should have the empty div where chat content belongs in a separate React component (my end goal is to have the parent component to immediately update the chat area whilst writing the content from the insert fields (username and text content) to the database collection)
I have Mongo database which contains a collection for chats (username/message) but my question is
A) how do I go about using axios to store the inserted username and text in the collection, and
B) once stored how would I allow the parent component (React) to immediately update them to the empty div (chatArea) from the mongo database so that upon page refresh, the users' old chats are still present?
Do I need componentDidMount()?
Do I need any middleware in my server.js file? (bodyparser etc.)
I am fairly new to using React js so bear with me. Also this is a fairly barebones chat that is focusing on functionality.
class Chat extends React.Component {
constructor(props){
super(props);
this.state = {
username: '',
message: '',
messages: []
};
}
render() {
return (
<div id="myChat">
<div id="status"></div>
<input type="text" id="username" class="form-control" placeholder="Enter Username..." value={this.state.username} onChange={ev => this.setState({username: ev.target.value})}>
</input>
<div id="chat">
<br></br>
<div class="card">
<div id="messages" class="card-block">
{this.state.messages.map(message => {
return (
<div>{message.author}: {message.message}</div>
)
})}
</div>
</div>
<br></br>
</div>
<textarea id="textarea" class="form-control" placeholder="Enter message..." value={this.state.message} onChange={ev => this.setState({message: ev.target.value})} ></textarea>
</div>
);
}
}
You have to need ur server for that is not necessary to use axios for that u can manage all thing with ur socket connection.
Server.js that manage ur backend which u want play with the database.
Server.js: implements a start the socket.
const io = require('socket.io')();
const AVATAR = 'https://i1.wp.com/tricksmaze.com/wp-content/uploads/2017/10/Stylish-Girls-Profile-Pictures-11.jpg';
const NAME = '#zoya';
io.on('connection', function (client) {
// console.log('client Id::', client.id)
//chat message
client.on('chat-message', function (messages) {
let { message } = messages;
let messageObj = {
sender: NAME,
avatar: AVATAR,
message
}
client.emit('chat-message', messageObj);
});
//disconnects...
client.on('disconnect', function () {
console.log('disconnect client Id::', client.id)
});
});
const port = 8000;
io.listen(port);
console.log('listening on port : ', port);
on client side.
'use static';
import React, { Component } from 'react';
import openSocket from 'socket.io-client';
const SERVER = `http://localhost:8000/`;
const NAME = '#asif';
const AVATAR = 'https://pbs.twimg.com/profile_images/874276197357596672/kUuht00m_400x400.jpg';
const AVATAR1 = 'https://i1.wp.com/tricksmaze.com/wp-content/uploads/2017/10/Stylish-Girls-Profile-Pictures-11.jpg';
class App extends Component {
constructor(props) {
super(props);
this.state = {
typing: '',
messages: []
}
this.socket = openSocket(SERVER);
this.chatMessage = this.chatMessage.bind(this);
}
componentDidMount() {
this.chatMessage();
}
chatMessage() {
this.socket.on('chat-message', (messageObj) => {
let { messages } = this.state;
messages.push(messageObj);
this.setState({ messages: messages })
})
}
sendMessage = () => {
let { messages, typing } = this.state;
if (typing && typing !== '') {
const message = typing;
this.setState({ typing: '' })
let messageObj = {
sender: NAME,
avatar: AVATAR,
message
}
messages.push(messageObj);
this.setState({ messages: messages })
this.socket.emit('chat-message', messageObj);
} else {
alert(`Message can't empty`);
}
};
renderItem() {
return this.state.messages.map((item,key)=>{
return (
<div >
<image src={ item.avatar } />
<div }>
<span >{item.sender}</span>
<span >{item.message}</span>
</div>
</div>
);
})
}
render() {
return (
<div >
<div >
<h1 >
Chat App
</h1>
</div>
{this.renderItem()}
<div >
<input
Type="text"
ref={ref => { this._messageInput = ref }}
placeholder="Type Message..."
value={this.state.typing}
onChangeText={text => this.setState({ typing: text })}
/>
<button onClick={() => this.sendMessage()}>
<span >Send</span>
</button>
</div>
</div>
);
}
}
export default App;
hope this help full for u.

Resources