firebase data to comparison in render - node.js

I need help to compare the firebase data (if)and render the right component.
Any help would be appreciated.
export default class EstoqueScreen extends Component {
constructor(props){
super(props);
var id=firebase.auth().currentUser.uid;
firebase.database().ref().child('users/'+id).once('value').then((snapshot) => {
var tipoUsuario=snapshot.val().tipo
});
}
render(){
console.log(this.tipoUsuario);
if(this.tipoUsuario==='admin'){
return(
<View>
<EstoqueAdminScreen/>
</View>
)
}else if(this.tipoUsuario==='vendedor'){
return(
<View>
<EstoqueVendScreen/>
</View>
)
}
}
}

export default class EstoqueScreen extends Component {
constructor(props){
super(props);
state = {
loading: true,
tipoUsuario: null,
}
}
componentDidMount(){
var id=firebase.auth().currentUser.uid;
firebase.database().ref().child('users/'+id).once('value').then((snapshot) => {
this.setState({ tipoUsuario: snapshot.val().tipo, loading: false })
});
}
render(){
console.log(this.state.tipoUsuario);
if(this.state.loading){
return (
<View>Loading</View>
)
}
if(this.state.tipoUsuario==='admin'){
return(
<View>
<EstoqueAdminScreen/>
</View>
)
}else if(this.state.tipoUsuario==='vendedor'){
return(
<View>
<EstoqueVendScreen/>
</View>
)
}
return (
<View>No hay tipo</View>
)
}
}

Related

Jest cannot read property of "searchForGames" of undefined

I am trying to create a test, that checks wether a component draws correctly or not. But when i try to run the test i get this error message:
TypeError: Cannot read property 'searchForGames' of undefined
I have tried adding som mock data in searchForGames, but i cant get it to work:(
Here is my code:
search.tsx
import * as React from "react";
import { Component } from "react-simplified";
import { CardGroup, GameCard, Container, NavBar, SubHeader, Alert } from "./widgets";
import { igdbService, Game } from "./services";
export class Search extends Component<{
match: { params: { searchString: string } };
}> {
games: Game[] = [];
render() {
return (
<Container>
{this.games.length !== 0 ? (
<CardGroup>
{this.games.map((game) => {
return (
<div key={game.id} className="col">
<NavBar.Link to={"/games/" + game.id}>
<GameCard
name={game.name}
url={game.cover ? game.cover.url.replace("thumb", "cover_big") : ""}
/>
</NavBar.Link>
</div>
);
})}
</CardGroup>
) : (
<div className="d-flex flex-column justify-content-center">
<h4 className="mx-auto">The game you are looking for could not be found in the IGDB database..</h4>
<img className="w-40 mx-auto" alt="Sadge" src="https://c.tenor.com/kZ0XPsvtqw8AAAAi/cat-farsi-sad.gif"/>
</div>
)}
</Container>
);
}
mounted() {
this.getGames();
}
getGames() {
igdbService
.searchForGames(this.props.match.params.searchString)
.then((response) => (this.games = response))
}
}
search.test.tsx
import {Search} from "../src/Search"
import * as React from "react";
import { shallow } from 'enzyme';
import { NavBar, GameCard } from "../src/widgets";
jest.mock("../src/services", () => {
class Service {
searchForGames(string: searchString) {
return Promise.resolve(
[
{
id:143755,
cover: {
id:1311803,
url: '//images.igdb.com/igdb/image/upload/t_thumb/co2tp7.jpg'
},
name: "Terrorist Killer",
}
]
)
}
getGames() {
return Promise.resolve();
}
}
return new Service();
})
test("Search draws correctly", (done) => {
const wrapper = shallow (<Search match={{params: {searchString: "Terrorist"} }}/>)
setTimeout(() => {
expect(
wrapper.containsAllMatchingElements([
<div>
<NavBar.Link to="/games/143755">
<GameCard
name="Terrorist Killer"
url="//images.igdb.com/igdb/image/upload/t_thumb/co2tp7.jpg"
/>
</NavBar.Link>
</div>
])
).toEqual(true);
done();
})
})

How to update the user feed after updating the post?

I have a UserFeed component and EditForm component. As soon as I edit the form, I need to be redirected to the UserFeed and the updated data should be shown on UserFeed(title and description of the post).
So, the flow is like-UserFeed, which list the posts, when click on edit,redirected to EditForm, updates the field, redirected to UserFeed again, but now UserFeed should list the posts with the updated data, not the old one.
In this I'm just redirectin to / just to see if it works. But I need to be redirected to the feed with the updated data.
EditForm
import React, { Component } from "react";
import { connect } from "react-redux";
import { getPost } from "../actions/userActions"
class EditForm extends Component {
constructor() {
super();
this.state = {
title: '',
description: ''
};
handleChange = event => {
const { name, value } = event.target;
this.setState({
[name]: value
})
};
componentDidMount() {
const id = this.props.match.params.id
this.props.dispatch(getPost(id))
}
componentDidUpdate(prevProps) {
if (prevProps.post !== this.props.post) {
this.setState({
title: this.props.post.post.title,
description: this.props.post.post.description
})
}
}
handleSubmit = () => {
const id = this.props.match.params.id
const data = this.state
this.props.dispatch(updatePost(id, data, () => {
this.props.history.push("/")
}))
}
render() {
const { title, description } = this.state
return (
<div>
<input
onChange={this.handleChange}
name="title"
value={title}
className="input"
placeholder="Title"
/>
<textarea
onChange={this.handleChange}
name="description"
value={description}
className="textarea"
></textarea>
<button>Submit</button>
</div>
);
}
}
const mapStateToProps = store => {
return store;
};
export default connect(mapStateToProps)(EditForm)
UserFeed
import React, { Component } from "react"
import { getUserPosts, getCurrentUser } from "../actions/userActions"
import { connect } from "react-redux"
import Cards from "./Cards"
class UserFeed extends Component {
componentDidMount() {
const authToken = localStorage.getItem("authToken")
if (authToken) {
this.props.dispatch(getCurrentUser(authToken))
if (this.props && this.props.userId) {
this.props.dispatch(getUserPosts(this.props.userId))
} else {
return null
}
}
}
render() {
const { isFetchingUserPosts, userPosts } = this.props
return isFetchingUserPosts ? (
<p>Fetching....</p>
) : (
<div>
{userPosts &&
userPosts.map(post => {
return <Cards key={post._id} post={post} />
})}
</div>
)
}
}
const mapStateToPros = state => {
return {
isFetchingUserPosts: state.userPosts.isFetchingUserPosts,
userPosts: state.userPosts.userPosts.userPosts,
userId: state.auth.user._id
}
}
export default connect(mapStateToPros)(UserFeed)
Cards
import React, { Component } from "react"
import { connect } from "react-redux"
import { compose } from "redux"
import { withRouter } from "react-router-dom"
class Cards extends Component {
handleEdit = _id => {
this.props.history.push(`/post/edit/${_id}`)
}
render() {
const { _id, title, description } = this.props.post
return (
<div className="card">
<div className="card-content">
<div className="media">
<div className="media-left">
<figure className="image is-48x48">
<img
src="https://bulma.io/images/placeholders/96x96.png"
alt="Placeholder image"
/>
</figure>
</div>
<div className="media-content" style={{ border: "1px grey" }}>
<p className="title is-5">{title}</p>
<p className="content">{description}</p>
<button
onClick={() => {
this.handleEdit(_id)
}}
className="button is-success"
>
Edit
</button>
</div>
</div>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
nothing: "nothing"
}
}
export default compose(withRouter, connect(mapStateToProps))(Cards)
updatePost action
export const updatePost = (id, data, redirect) => {
return async dispatch => {
dispatch( { type: "UPDATING_POST_START" })
try {
const res = await axios.put(`http://localhost:3000/api/v1/posts/${id}/edit`, data)
dispatch({
type: "UPDATING_POST_SUCCESS",
data: res.data
})
redirect()
} catch(error) {
dispatch({
type: "UPDATING_POST_FAILURE",
data: { error: "Something went wrong"}
})
}
}
}
I'm not sure if my action is correct or not.
Here's the updatePost controller.
updatePost: async (req, res, next) => {
try {
const data = {
title: req.body.title,
description: req.body.description
}
const post = await Post.findByIdAndUpdate(req.params.id, data, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}
One mistake is that to set the current fields you need to use $set in mongodb , also you want to build the object , for example if req.body does not have title it will generate an error
updatePost: async (req, res, next) => {
try {
const data = {};
if(title) data.title=req.body.title;
if(description) data.description=req.body.description
const post = await Post.findByIdAndUpdate(req.params.id, {$set:data}, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}

Redirect after a post request with data in react js / node js

I'm trying to send data to another component page after doing a post request to my node js server.
first component to redirect: (I cannot post all my code, it is to big
fetch('http://localhost:8080/createVolume', requestOptions)
.then(response => response.json())
.then(data => {
console.log(data);
this.setState({
ansibleAnswer: data,
submitted: true
})
console.log(this.state.ansibleAnswer);
});
.
.
.
// uderneeth my render
} else if (this.state.loaded === true && this.state.submitted === true) {
return (
<Redirect to={{
pathname: '/Completed',
state: { name: this.state.name, result: this.state.ansibleAnswer }
}}
/>
);
new component after post request:
class Completed extends React.Component {
constructor(props) {
super(props);
this.state = {
name: this.props.location.state.name,
result: this.props.location.state.ansibleAnswer
};
}
render() {
return (
<div>
<Header />
<div>
<p>test successful</p>
<p>{this.state.result}</p>
</div>
<Footer />
</div>
);
}
}
export default Completed;
I get this error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
I understand that the data isn't saved in the state but I don't understand how I could save it (or wait) before sending the data to the other component.
thank you
class Completed extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
result: ''
};
}
/** When the Completed component does anything with the new props,
* componentWillReceiveProps is called, with the next props as the argument */
componentWillReceiveProps(nextProps) {
/** Update state**/
if (nextProps.location.state.result !==
this.props.location.state.result) {
this.setState({
result:nextProps.location.state.result
});
}
}
render() {
return (
<div>
<Header />
<div>
<p>test successful</p>
<p>{this.state.result}</p>
</div>
<Footer />
</div>
);
}
}
export default Completed;

Component are not update after redirect back from Nodejs

I've created small ReactJS app and get retrieve user feeds data from facebook api.
If data not shown, call NodeJS api and fetch feeds from facebook and redirect back to index screen. Problem is once redirect back, I found that feeds is already in database and after redirect back to index page, feeds are not shown, I need to reload browser screen.
My problem is which component should I use after redirect back to original screen in react?
import React, { Component } from 'react';
import ReloadButton from './ReloadButton';
import Feeds from './Feeds';
import Alert from './Alert';
class MyTest extends Component {
constructor(props) {
super(props);
this.state = {
feeds: []
};
}
componentDidMount() {
fetch('/fetch')
.then(response => response.json())
.then(data => this.setState({ feeds: data }));
}
render() {
const { feeds } = this.state;
return (
<div className="container-fluid">
<a className="btn btn-primary" href="/auth/facebook">Reload</a>
{ feeds.length > 0 ? <Feeds feeds={ feeds } /> : <Alert /> }
</div>
);
}
}
export default MyTest;
if I were you I did something like this. please say if it is helpful
interface ExampleProps {
someDataFacebookSendMe: any; //this prop used to get redirect from facebook and for first time is null
}
interface ExampleState {
feeds: []
spinning: boolean;
isDataCollected: boolean; // this proprty check for gotten data
}
export class Example extends React.Component<ExampleProps, ExampleState> {
constructor(props) {
super(props);
this.state = {
feeds: [],
spinning: true,
isDataCollected: false
};
}
componentDidMount() {
if (!!this.props.someDataFacebookSendMe) {
while (!this.state.isDataCollected) {
this.getData()
}
fetch('/fetch')
.then(response => response.json())
.then(data => {
if (data !== null && data !== undefined) {
this.setState({ feeds: data, spinning: false, isDataCollected: true })
}
});
}
else {
this.setState({spinning: false})
}
}
getData() {
fetch('/fetchIsDataExists') // this method check if data has gotten or not
.then(data => this.setState({isDataCollected: true }));
}
render() {
const { feeds } = this.state;
return (
<div className="container-fluid">
<Spin spinning={spinning} >
<a className="btn btn-primary" href="/auth/facebook">Reload</a>
{feeds.length > 0 ? <Feeds feeds={feeds} /> : <Alert />}
</Spin>
</div>
);
}
}

When I use flatlist in RN, I find this error: Cannot read property 'loginname' of undefined

I just want show a list of the site data to FlatList component,but I find an error:
TypeError: Cannot read property 'loginname' of undefined
therefore, I change '{item.author.loginname}' to '{item.author}', I get this error:
Unhandled JS Exception: Invariant Violation: Objects are not valid as a
React child (found: object with keys {loginname, avatar_url}). If you meant to render a collection of
Actually, property 'loginname' is exists. I am confused. Why?
Here is my code:
import React, { Component } from 'react';
import { Text, ScrollView, View, StyleSheet, FlatList,Image } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
stories: [{id: 1, text: 'option1'}, {id: 2, text: 'option2'}, {id: 3, text: 'option3'}],
isFetching: false,
};
}
componentDidMount() {
this.fetchData();
}
onRefresh() {
console.log('refreshing')
this.setState({ isFetching: true }, function() {
this.fetchData()
});
}
fetchData() {
var url = "https://cnodejs.org/api/v1/topics?limit=1&mdrender=true"
fetch(url, {method: "GET"})
.then((response) => response.json())
.then((responseData) => {
this.setState({stories: responseData.data,isFetching: false})
console.log( responseData.data[0].author.loginname,responseData.data[0].visit_count)
})
.done();
}
_renderItem = ({item}) => (
<View>
<Text>{item.author.loginname}</Text>
</View>
)
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.wrapper}>
<Text>Hello World!!!</Text>
<FlatList
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
data={this.state.stories}
keyExtractor={(item) => item.id}
renderItem={this._renderItem}
/>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
// alignItems: 'center',
// justifyContent: 'center',
paddingTop: 50,
backgroundColor: '#ecf0f1',
}
});
This issue occurs because of your initial state which is set in constructor. When first-time component try to render at that time it tacks story' state from constructor because of your API fetch tack some moment to complete call.
Just replace your constructore by following line.
constructor(props) {
super(props);
this.state = {
stories: [],
isFetching: false,
};
}
This problem occurred because your view loads first and then your api get called. So your stories is undefined.
Small Update to your code:
this.state = {
stories: null,
isFetching: false,
};
View inside render:
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.wrapper}>
<Text>Hello World!!!</Text>
{this.state.stories !== null ?
<FlatList
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
data={this.state.stories}
keyExtractor={(item) => item.id}
renderItem={this._renderItem}
/>
: null
}
</View>
</ScrollView>
);
}
Output:
Hello World!!
atian25

Resources