Get data fro firestore with React Native - javascript

I need to get data from Firestore but i can't, i need to know if my code is ok, because it doesn't work or something else is missing.
This is my firestore services
fireservices.js
import React from 'react';
import * as firebase from 'firebase';
import { firebaseConfig } from '../firebase_const';
import 'firebase/firestore';
firebase.initializeApp(firebaseConfig)
class FireServices{
static async getLocalization(idOfert) {
firebase.firestore.collection('users').doc(idOfert)
}
}
export default FireServices;
And this is my class, this class use the method to get data
SecondClass.js
import React from 'react';
import FireServices from '../services/fireservices';
export default class SecondClass extends React.Component {
componentDidMount = async () => {
this.onStart()
}
onStart = () => {
FireServices.getLocalization('email#hotmail.com').get().then(doc => {
console.log(doc)
})
}
render(){
return (
<View>
</View>
)
}

You are not returning from getLocalization.
It should be
static async getLocalization(idOfert) {
return firebase.firestore.collection('users').doc(idOfert)
}

Related

Mobx store in react doesn't rerender components

I'm trying to understand mobx. After annotations caused a lot of trouble, I decided to use a global store as described here. My store looks like this:
import {
makeObservable,
observable,
action
} from "mobx";
class Store {
constructor() {
makeObservable(this, {
fetchWorkouts: action,
user: observable,
allWorkouts: observable,
selectedWorkout: observable,
currentStep: observable,
setUser: action
})
}
user = {
uid: null,
email: null,
name: null
}
allWorkouts = []
selectedWorkout = {}
currentStep = 0
fetchWorkouts() {
}
setUser(newUser) {
this.user = newUser;
}
}
const store = new Store()
export default store;
My new user comes directly from the login, which looks like this:
import {Button} from "semantic-ui-react";
import {useHistory} from "react-router-dom"
import React from 'react';
import store from "../../context/Store";
import {toJS} from "mobx";
export default function SubmitLogin(props) {
let history = useHistory();
// eslint-disable-next-line react-hooks/exhaustive-deps
const loginUser = async () => {
let bodyObj = {
email: props.email,
pw: props.password
}
let queryString = "http://localhost:3001/user/login/" + bodyObj.email + "/" + bodyObj.pw;
await fetch(queryString).then(response => response.json()).then(json => store.setUser(json)).then(() => console.log(toJS(store.user))).then(() => history.push("/"));
}
return (
<>
<Button className={"loginRegisterButton"} onClick={loginUser}>Submit</Button>
</>
)
}
To test everything, I am trying to display the uid in my header like this:
import React, {Component} from 'react';
import {Link} from "react-router-dom";
import store from "../context/Store";
class Toolbar extends Component {
render() {
return (
<div id={"toolbarDiv"}>
<p style={{color: "white"}}>{store.user.uid}</p>
</div>
);
}
}
export default Toolbar
However, even after I receive the uid from my server and can print it in my login component, I assume that the data gets correctly assigned to the user variable in the store. Unfortunately, after pressing the sign in button and getting redirected to "/", there is nothing in the toolbar. How can I access the variables correctly?
I think you still need to wrap Toolbar and SubmitLogin in an observer call:
import React, {Component} from 'react';
import {Link} from "react-router-dom";
import { observer } from "react-mobx";
import store from "../context/Store";
class Toolbar extends Component {
render() {
return (
<div id={"toolbarDiv"}>
<p style={{color: "white"}}>{store.user.uid}</p>
</div>
);
}
}
export default observer(Toolbar);
Ref: https://mobx.js.org/react-integration.html

Context empty after async initialisation

I am trying to fetch data from a backend API and initialise my FieldsContext. I am unable to do it, it returns an empty fields array in the Subfields component. I have spent hours on fixing it. But I eventually give up. Please take a look into this. Thanks in advance.
Here is my code
App.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css'
import './App.css';
import Index from './components/pages/index/'
import FieldsProvider from './providers/fieldProvider'
import AuthProvider from './providers/authProvider'
import {BrowserRouter as Router,Switch,Route} from 'react-router-dom';
import SubFields from './components/pages/subfields';
function App() {
return (
<Router>
<AuthProvider>
<FieldsProvider>
<Switch>
<Route exact path="/" component={Index} />
<Route exact path="/:fieldid/subfields" component={SubFields} />
</Switch>
</FieldsProvider>
</AuthProvider>
</Router>
);
}
export default App;
FieldsContext.js
import React from 'react'
const FieldsContext = React.createContext();
export default FieldsContext
FieldsProvider.js
import React, { Component } from 'react'
import FieldsContext from '../libs/fieldContext'
export default class FieldsProvider extends Component {
state = {fields:[]}
getFields()
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
Subfields.js
import React, { Component } from 'react'
import FieldsContext from '../../../libs/fieldContext'
import FieldsList from '../../Fields/fieldlist'
export default class SubFields extends Component {
componentDidMount(){
// const fieldId = this.props.match.params.fieldid;
console.log(this.context);
}
render() {
return (
<div>
</div>
)
}
}
SubFields.contextType = FieldsContext
try using an ES6 Arrow function, which binds the function to the object instance, so that this refers to the object instance of the class when it is called.
When its called asynchronously, this will refer the the class object instance you want to update.
import React, { Component } from 'react'
import FieldsContext from '../libs/fieldContext'
export default class FieldsProvider extends Component {
state = {fields:[]}
// ES6 Arrow function
getFields = () =>
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
Alternatively, Try binding of your function in the class constructor.
export default class FieldsProvider extends Component {
state = {fields:[]}
constructor(props) {
//bind the class function to this instance
this.getFields = this.getFields.bind(this);
}
//Class function
getFields()
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
As a side note: Prefer to use functional components for consuming of ContextAPI.
import React, { Component } from 'react'
import FieldsContext from '../../../libs/fieldContext'
import FieldsList from '../../Fields/fieldlist'
export default function SubFields (props) {
const {
match
} = props;
//much better way to consume mulitple Contexts
const { fields } = React.useContext(FieldsContext);
//useEffect with fields dependency
React.useEffect(() => {
console.log(fields);
},[fields]);
return (
<div>
</div>
)
}

this.props.match.params passed into child component after authorisation

I have recently started building a big project on React using also a Firebase with authentication and I cannot quite understand the relation between the react-router-dom links and React components.
I am struggling with getting the
this.props.match.params // which is going to be 2018 / 2019 / 2020... etc
in the component, which renders as a dynamic route (like unique post component).
I have tried to use only a simple class component and this works but the problem is, without the authentication everyone can access this admin route and everyone would be allowed to edit and delete data there. I want it to be accessed only by authenticated users. (Admins)
So this is how my piece of code looks like:
Main component: (where the link is)
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
class SeasonBox extends Component {
render() {
return (
<Link className='seasonbox' to={`/adminseason/${this.props.season}`}>
<p className='seasonbox__season'>{this.props.season}/{this.props.season+1}</p>
</Link>
)
}
}
export default SeasonBox;
And the component that renders after the link is clicked:
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import { compose } from 'recompose'
import { withAuthorisation } from '../Session'
import { withFirebase } from '../Firebase'
const AdminMatchesBox = ({authUser}) => (
<div>{authUser ? <AdminMatchesBoxAuth /> : <AdminMatchesBoxNonAuth />} </div>
)
class AdminMatchesBoxAuth extends Component {
render() {
return (
<div>
Hey I am the season {this.props.match.params}!
<Link to={'/adminmatches'}>Wróć</Link>
</div>
)
}
}
const AdminMatchesBoxNonAuth = () => (
<div>
<h1>You do not have permission to visit this page.</h1>
</div>
)
const mapStateToProps = state => ({
authUser: state.sessionState.authUser
});
const condition = authUser => !!authUser
export default compose(withAuthorisation(condition), connect(mapStateToProps),withFirebase)(AdminMatchesBox);
So if I don't use authorisation, and I use only a single class component I can get this.props.match.params -> which is the id of the website and I need it to access data from the database.
However, I want it to not be visible by not logged users and I had to process it through the authorisation process.
I am receiving an error
Cannot read property 'params' of undefined.
I have no clue how to pass match.params into the AdminMatchesBoxAuth component.
Could anyone advice?
By wrapping withRouter you able to access params
Try this
import { withRouter } from "react-router";
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import { compose } from 'recompose'
import { withAuthorisation } from '../Session'
import { withFirebase } from '../Firebase'
const AdminMatchesBox = ({authUser}) => (
<div>{authUser ? <AdminMatchesBoxAuth /> : <AdminMatchesBoxNonAuth />} </div>
)
class AdminMatchesBoxAuth extends Component {
constructor (props){
super(props)
}
render() {
return (
<div>
Hey I am the season {this.props.match.params}!
<Link to={'/adminmatches'}>Wróć</Link>
</div>
)
}
}
const AdminMatchesBoxNonAuth = () => (
<div>
<h1>You do not have permission to visit this page.</h1>
</div>
)
const mapStateToProps = state => ({
authUser: state.sessionState.authUser
});
const condition = authUser => !!authUser
export default compose(withRouter, withAuthorisation(condition), connect(mapStateToProps),withFirebase)(AdminMatchesBox)

Redux store value set in callback

new to react-redux.I am facing a problem while working with redux store.
Data for store is loaded from API.Flow of my code is as follows:
app.js:
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Schema from './components/Schema';
import './styles/bootstrap.css';
import './styles/main.css';
export default class App{
constructor(props) {
super(props);
this.state = { store: {}};
}
componentWillMount(){
store(storeObject => {
this.setState({store: storeObject});
});
}
render(){
return <Provider store={ this.state.store }><Schema /></Provider>
}
}
store/index.js:
export default function(next) {
getInitialState(function(initialState) {
store = createStore(Reducers, initialState, compose(applyMiddleware(...middleware), extension));
console.log(store);//returning correct store value
next(store);
});
};
main.js:
import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './app.js';
const dom = document.getElementById('root');
render(
<AppContainer>
<App />
</AppContainer>,
dom
);
it is giving following error.
The store function which I guess is a reference to the getStore function doesn't return anything which means that App doesn't return anything hence the exception.
Because getStore does an async operation, you'll have to do something like this:
export default class App extends Component{
componentWillMount(){
store(storeObject => {
this.setState({store: storeObject});
});
}
render(){
return <Provider store={ this.state.store }><Schema /></Provider>
}
}

React import module error

Simply what im trying to do is export a function that make a mongodb query and import it into a react component so i can call it there and display the data.
this is the error i keep getting: ./node_modules/require_optional/node_modules/resolve-from/index.js
Module not found: Can't resolve 'module' in '/Users/paul/Desktop/TempProject/Dietx/dietxweb/node_modules/require_optional/node_modules/resolve-from'
react component, Diet.js:
import React, {Component} from 'react';
import getItemList from '../server/api.js';
import ReactList from 'react-list';
class Diet extends Component {
constructor(props){
super(props)
this.state ={
Calories : 3000,
Items: [],
}
}
componentWillMount(){
}
render(){
return(
<div className="diet-container">
<p>lol</p>
</div>
)
}
}
export default Diet;
API, api.js:
const mongo = require('mongodb');
export const getItemList = ()=>{
var url = "mongodb://localhost:27017/food"
return(
mongo.connect(url)
.then((db)=>{
return db.collection('foodInfo')
})
.then((res)=>{
return res.find().toArray()
})
)
}
Change
export const getItemList = ()=>{
to
export default function getItemList() {
The syntax you are using is importing the default member from the module but your module does not define a default member.
Alternatively, you could use the syntax
import {getItemList} from ...

Categories