I have tried a lot to get this done but i dont know why the json is not printing on the DIV tag
I am getting a user1 is undefined
i am using my own api to fetch data which is populate in users.
{ success: true, user: "Normal User" }
JSON is as above
got the authorized token and logged in with it successfully but when i get the JSOn i cant show the user in the HTML page
please help!
Thanks in advance
this is my HomePage.jsx
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { userActions } from '../_actions';
class HomePage extends React.Component {
componentDidMount() {
this.props.dispatch(userActions.getAll());
}
render() {
var { user, users1 } = this.props;
console.log(user); // token
console.log(users1); // json with names and all
return (
<div className="col-md-6 col-md-offset-3">
<h1>Hi {users1.user} !</h1>
<p>
<Link to="/login">Logout</Link>
</p>
</div>
);
}
}
function mapStateToProps(state) {
const { users, authentication } = state;
const { user } = authentication;
// var users1 = {"success":true,"user":"Normal User"}
var users1 = users.users
return {
user,
users1
};
}
const connectedHomePage = connect(mapStateToProps)(HomePage);
export { connectedHomePage as HomePage };```
Looks like you didn't parse JSON after the fetch and users1 in your case is a string. Try JSON.parse(users1).
Related
I have two js files, including login and sidebar.
In the login.js(class component), it will call the loginAction to perform an API call and get back response data(id, role, username).
import LoginAction from auth.js
...
handleSubmit(event) {
event.preventDefault();
var response = LoginAction(this.state)
}
LoginAction is in the auth.js
export function LoginAction(data) {
const loginName = data.loginName;
const password = data.password;
var response = Login(loginName, password).then(response => {
if (response.data.errorCode === "") {
sessionStorage.setItem("token", response.data.data.token)
return {passwordError: null, loginNameError: null, isLoggedOn: true, role: response.data.data.isAdmin};
} else {
return formatError(response.data);
}
})
return response;
};
Here is the Login which is in the authservice.js
export const Login = (loginName, password) => {
const postData = { loginName, password }
console.log(postData);
return Axios.post("http://localhost:8080/login", postData, header);
}
how to pass the response to sidebar.js(class component)? I want to display the user's role on the sidebar.
if (data.isLoggedOn) {
console.log("routing to /employee")
this.props.router.navigate("/employee", { state: { "id": id, "role": role } })
}
I have tried to use the state to pass the data, but the role cannot be loaded to the sidebar after the first loading. The role only displays when I load the sidebar page again.
You can create a state in a common parent component and pass down a function that sets that state. Here's a quick example where I define a state user in the App and define login() which sets its state. Then I pass login() as a prop to the login button, and pass user as a prop to the sidebar.
CodeSandbox
import React, { Component } from "react";
export default class App extends Component {
constructor(){
super();
this.state = {user: null}
}
login(user) {
this.setState({user})
}
render() {
return (
<div className="App">
<Login loginHandler={(user)=>this.login(user)}/>
<Sidebar user={this.state.user}/>
</div>
);
}
}
class Sidebar extends Component{
render(){
return(
<div className="sidebar">Hey {this.props.user}</div>
)
}
}
class Login extends Component{
render(){
return(
<button onClick={()=>this.props.loginHandler('Foo')}>Login</button>
)
}
}
I'm using nextjs to create a dashboard and I have the authentication using next-auth.
However, I'm trying to render the individual users data when they login to the dashboard but not sure where I'm going wrong, I know I have to use the findOne callback but for some reason I can't grab the ID or email.
Here is what I have so far
import { connectToDatabase } from '../../lib/mongodb';
import Head from 'next/head';
import Sidebar from '../components/Sidebar';
export default function Dashboard({ user }) {
return (
<>
<Head>
<title>Ellis Development - Dashboard</title>
</Head>
<Sidebar />
<section className="content dashboard-content">
<h1>Dashboard</h1>
{ users.map(user => (
<div key={user.id}>
<h2>{user.firstname} {user.lastname}</h2>
<p>{user.email}</p>
</div>
)) }
</section>
</>
)
}
// get data from database using server side rendering and mongodb connection
export async function getServerSideProps() {
const client = await connectToDatabase();
const users = await client.db().collection('users').findOne({ _id: id }).toArray();
return {
props: {
users: JSON.parse(JSON.stringify(users))
}
}
}
You can use getSession to handle server-side authentications.
check reference for more resources link
import { getSession } from "next-auth/react"
...
export async function getServerSideProps(ctx) {
const session = await getSession(ctx) //pass context to authenticate create session
const id = session.user.id //get id from session
const client = await connectToDatabase();
const user = await client.db().collection('users').findOne({ _id: id }) // No need to use toArray its returns only 1 object
return {
props: {
user
}
}
}
I am building a web application in which i need to verify the user's email sent via the client side (React.js and Next.js) and i'm following this youtube tutorial. However, the mentor is using create-react-app CLI and React-Router-Dom for the routing system which doesn't really go with my current needs.
Moreover, I found this method online using HOC :
import React from 'react';
import Router from 'next/router';
const login = '/register?redirected=true'; // Define your login route address.
const checkUserAuthentication = () => {
return { auth: null }; // change null to { isAdmin: true } for test it.
};
export default WrappedComponent => {
const hocComponent = ({ ...props }) => <WrappedComponent {...props} />;
hocComponent.getInitialProps = async (context) => {
const userAuth = await checkUserAuthentication();
// Are you an authorized user or not?
if (!userAuth?.auth) {
// Handle server-side and client-side rendering.
if (context.res) {
context.res?.writeHead(302, {
Location: login,
});
context.res?.end();
} else {
Router.replace(login);
}
} else if (WrappedComponent.getInitialProps) {
const wrappedProps = await WrappedComponent.getInitialProps({...context, auth: userAuth});
return { ...wrappedProps, userAuth };
}
return { userAuth };
};
return hocComponent;
};
The code above helps me to have a private route that the user cannot access unless he's authenticated (currently no programming included), but on the other hand i still need a page in the following route :
'pages/user/activate/[token].js' // the link sent via email from express back end.
What i need now is to create this page using Next routing system in order to get the token and decode it to move forward with the back end and save the user into MongoDB, and in order to accomplish that, i have created my [token].js page with the following code :
import React, {useState, useEffect} from 'react'
import { ToastContainer, toast } from 'react-toastify';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import { authenticate, isAuth } from '../helpers/auth';
import { Link, Redirect } from 'react-router-dom';
const Activate = ({ match }) => {
const [formData, setFormData] = useState({
email: '',
token: '',
show: true
});
const { email, token, show } = formData;
useEffect(() => {
let token = match.params.token;
let { email } = jwt.decode(token);
if (token) {
setFormData({ ...formData, email, token });
}
console.log(token, email);
}, [match.params.token]);
return (
<>
{isAuth() ? <Redirect to="/" /> : null}
<p>Account activated, please log in</p>
</>
)
};
export default Activate;
However, i keep getting this error :
TypeError: Cannot read property 'params' of undefined
at Activate (C:\Users\Hp\Desktop\SMP\client\.next\server\pages\user\activate\[token].js:245:13)
at processChild (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3353:14)
at resolve (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-
dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3690:29)
at renderToString (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:4298:27)
at Object.renderPage (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\server\render.js:53:851)
at Function.getInitialProps (C:\Users\Hp\Desktop\SMP\client\.next\server\pages\_document.js:293:19)
at loadGetInitialProps (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\lib\utils.js:5:101)
at renderToHTML (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\server\render.js:53:1142)
I couldn't find a solution because i believe that i'm doing something wrong whether in my code or in the logic implemented.
Is there any way that i can do this properly ?
Thank you in advance !
I have been using stripe checkout in my react application for about a week now. However, I now receive an error that says "Stripe Checkout can't communicate with our payment processor because the API key is invalid. Please contact the website owner or support#stripe.com." I have no idea why this is happening now. I just want to be able to send my total into the stripe modal.
stripe.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import { connect } from "react-redux";
import { purchase } from "../actions/StoreActions";
import { toast } from "react-toastify";
import StripeCheckout from "react-stripe-checkout";
const mapStateToProps = (state) => {
return {
cart: state.cart,
total: state.total
};
};
const mapDispatchToProps = (dispatch) => {
return {
purchase: (order) => {
dispatch(purchase(order));
}
};
};
function Stripe(props) {
console.log(props);
const [product] = React.useState({
name: `$${props.total}`,
price: props.total
});
async function handleToken(token, address) {
props.startLoading();
const response = await axios.post(
"https://storebe.herokuapp.com/checkout",
{
token,
product
}
);
const { status } = response.data;
if (status === "success") {
props.stopLoading();
console.log(address);
purchaseCartItems(address);
} else {
props.stopLoading();
toast("Failed, please try again", { type: "error" });
}
console.log(response.data);
}
return (
<div className="container">
<StripeCheckout
stripeKey="pk_test_51HF9J6FriexrfnPAT0b3P1wDiKx1YQzONJrB5F4ksTidko10JKZOTgo7zuPjj9NWquykYNnMz1GRyQ5LDI2HvrEF00U49BhKdn"
token={handleToken}
amount={props.total * 100}
billingAddress
shippingAddress
name={product.name}
/>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Stripe);
There isn't a way to validate if an API key is actually a valid Stripe API key.
The issue on your end is most likely because the publishable key in your code has a typo in it.
You just have to make sure that the API keys you copy from https://dashboard.stripe.com/test/apikeys are correct and don't have any copy paste errors like extra white space, etc.
I'm attempting to make a simple RSS feed reader that will allow a user to enter a url in a search bar and display the results using Meteor and React. In my current set up, I have a SearchBar component with a function that makes a call to the meteor method on the server. How can I store the return of the API call in a client side collection? I've seen some examples on using publish and subscribe to do this, but haven't been able to follow. My goal is to save this data in a client side collection so I can access it from any components that will need it, and not have to render subsequent components through the SearchBar component's render method. This is how I currently have it set up:
feeds.js
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import parser from 'rss-parser';
if(Meteor.isServer) {
Meteor.methods({
getFeed(url) {
this.unblock();
const feed = {
title: '',
entries: []
};
try {
console.log('trying to get url');
const response = HTTP.get(url);
parser.parseString(response.content, function(err, parsed) {
feed.title = parsed.feed.title;
parsed.feed.entries.forEach(function(entry) {
feed.entries.push(entry);
})
});
console.log(feed.title);
return feed;
} catch(e) {
return false;
}
}
});
}
SearchBar.js
import React, { Component } from 'react';
import { Tracker } from 'meteor/tracker';
import FeedList from './FeedList';
export default class SearchBar extends Component {
constructor(props) {
super(props);
this.state = {
results: null,
url: ''
}
}
onSubmit(e) {
const { url } = this.state;
e.preventDefault();
const response = Meteor.call('getFeed', url, (err, res) => {
if(!err) {
this.setState({
results:res.entries
});
console.log(this.state.results);
} else {
console.log(err.reason);
}
});
}
onChange(e) {
this.setState({
url: e.target.value
});
}
render() {
return (
<div>
<form onSubmit={this.onSubmit.bind(this)}>
<input type="text" placeholder="Enter a URL" value={this.state.url} onChange={this.onChange.bind(this)}/>
<button type="submit">Get Feed</button>
</form>
{this.state.results ? <FeedList feedItems={this.state.results}/> : <p>Load a feed</p>}
</div>
);
}
}
Don't get the feed on the server at all. Get it on the client, and save it using a local collection defined like:
let localCollection = new Mongo.Collection(null)
Regarding the comments:
A typical pattern for this is for a cron job to populate a collection that is published to the client and rendered there.
This is going to be way over-engineered for your needs, and it's commonly regarded as a canonically wrong answer.