Navigate from one page to another on Button click - javascript

Hey I'm trying to make a Student Management System, where I made a Login page,Signup and a Dashboard page.
Now, while clicking a Button 'Fill Details' from my Dashboard page I need to navigate to another page input.js (Which is actually a separate project). I'll link my code below. Please help me to make it!
//input.js
import React, { Component } from 'react';
import web3 from './web3';
import ipfs from './ipfs';
import storehash from './storehash';
import { Button } from 'reactstrap';
class MyComponent extends Component {
state = {
ipfsHash:null,
buffer:'',
ethAddress:'',
transactionHash:'',
txReceipt: ''
};
//Take file input from user
captureFile =(event) => {event.stopPropagation()
event.preventDefault()
const file = event.target.files[0]
let reader = new window.FileReader()
reader.readAsArrayBuffer(file)
reader.onloadend = () => this.convertToBuffer(reader) };
//Convert the file to buffer to store on IPFS
convertToBuffer = async(reader) => {
//file is converted to a buffer for upload to IPFS
const buffer = await Buffer.from(reader.result);
//set this buffer-using es6 syntax
this.setState({buffer});};
//ES6 async
functiononClick = async () => {try{this.setState({blockNumber:"waiting.."});
this.setState({gasUsed:"waiting..."});
await web3.eth.getTransactionReceipt(this.state.transactionHash, (err, txReceipt)=>{
console.log(err,txReceipt);
this.setState({txReceipt});
});
}
catch(error){
console.log(error);
}}
onSubmit = async (event) => {
event.preventDefault();
//bring in user's metamask account address
const accounts = await web3.eth.getAccounts();
//obtain contract address from storehash.js
const ethAddress= await storehash.options.address;
this.setState({ethAddress});
//save document to IPFS,return its hash#, and set hash# to state
await ipfs.add(this.state.buffer, (err, ipfsHash) => {
console.log(err,ipfsHash);
//setState by setting ipfsHash to ipfsHash[0].hash
this.setState({ ipfsHash:ipfsHash[0].hash });
// call Ethereum contract method "sendHash" and .send IPFS hash to etheruem contract
//return the transaction hash from the ethereum contract
storehash.methods.sendhash(this.state.ipfsHash).send({
from: accounts[0]
},
(error, transactionHash) => {
console.log(transactionHash);
this.setState({transactionHash});
});
})
};
render() {
return (
<div className="App">
<header className="App-header">
<h1>EduDecentro</h1>
</header>
<hr/>
<grid>
<h5> Choose Transcript file </h5>
<form onSubmit={this.onSubmit}>
<input
type = "file"
onChange = {this.captureFile}
/>
<Button
bsStyle="primary"
type="submit">
Send it
</Button>
</form>
<tbody>
<tr>
<td>IPFS Hash</td>
<td> : </td>
<td>{this.state.ipfsHash1}</td>
</tr>
</tbody>
<h5> Choose Certificate-1 file </h5>
<form onSubmit={this.onSubmit}>
<input
type = "file"
onChange = {this.captureFile}
/>
<Button
bsStyle="primary"
type="submit">
Send it
</Button>
</form>
<tbody>
<tr>
<td>IPFS Hash</td>
<td> : </td>
<td>{this.state.ipfsHash2}</td>
</tr>
</tbody>
<h5> Choose Certificate-2 file </h5>
<form onSubmit={this.onSubmit}>
<input
type = "file"
onChange = {this.captureFile}
/>
<Button
bsStyle="primary"
type="submit">
Send it
</Button>
</form>
<h5> Choose Resume file </h5>
<form onSubmit={this.onSubmit}>
<input
type = "file"
onChange = {this.captureFile}
/>
<Button
bsStyle="primary"
type="submit">
Send it
</Button>
</form><hr/>
</grid>
</div>
);
}}
export default MyComponent;
import React from 'react';
import {Link } from "react-router-dom";
function Dashboard(props) {
// handle click event of logout button
const handleLogout = () => {
props.history.push('/Sign-in');
}
return (
<div>
Welcome User!<br /><br />
<Link to="/input"><button>
Fill Details
</button>
</Link>
<input type="button" onClick={handleLogout} value="Logout" />
</div>
);
}
export default Dashboard;

All you have to do is to add event listener for your Fill Details button, you don't need to wrap it into the Link component. Here is the example:
<button onClick={() => window.location.href = 'YOUR_LINK_TO_ANOTHER_APP' }>
Fill Details
</button>

<button onClick="window.location.href='Second_App_Page_Link';">Click Here
</button>

Related

How to change the url for signin page in next-auth?

In Next.js project I've implemented authentication with Next-Auth.
In index.js (as the Next-Auth documentation explains) I return a User only if there is a session
export default function Home({characters}) {
const {data: session} = useSession()
return (
<>
<Meta
description="Generated by create next app"
title={!session ? "Home - Login" : `Home - ${session.user.name}`}
/>
{session ? <User session={session} /> : <Guest/>}
</>
)
}
In the Guest component I have a Sign In button, and the onClick event points to the signIn method from "next-auth/react"
function Guest() {
return <Layout className="flex flex-col h-screen">
<div className="font-extrabold mb-4 text-3xl">GUEST USER</div>
<Button onClick={() => signIn()}>Sign In</Button>
</Layout>
}
as soon as I click that button I'm redirected to this pages/auth/signin.js page.
This is the page where I can login through EmailProvider or GoogleProvider
import { getCsrfToken, getProviders, signIn } from "next-auth/react"
import { Meta, Layout, Card, InputGroup, Button } from "../../components/ui";
export default function SignIn({ csrfToken, providers }) {
return (
<Layout>
<Meta title="Login"/>
<Card>
<form method="post" action="/api/auth/signin/email">
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
<InputGroup
type="email"
htmlFor="email"
label="Email"
name="email"
/>
<Button type="submit">Sign in with Email</Button>
</form>
{Object.values(providers).map((provider) => {
if(provider.name === "Email") {
return
}
return (<div className="mt-3" key={provider.name}>
<Button onClick={() => signIn(provider.id)}>
Sign in with {provider.name}
</Button>
</div>)
})}
</Card>
</Layout>
)
}
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken(context)
const providers = await getProviders()
return {
props: { csrfToken, providers },
}
}
When I'm in this page the url is http://localhost:3000/auth/signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000
I wanna know if it's possible to change that url to a more polite one like http://localhost:3000/login or something like this.
This page is already a custom login page as you can see in my [...nextauth].js
pages: {
signIn: '/auth/signin',
},
any suggestions? Thanks guys!
Yes it should work. Lets say you put this in your [...nextauth].js options
pages: {
signIn: '/login'
}
The signIn button will now redirect to /login.
Then you just have to put your login page under pages: pages/login.js.

Handling action in Remix.run without POST

I read up on the Remix docs on action and most of information I can find on action is it uses the the form POST with button submit to trigger the action
export default function Game() {
const counter = useLoaderData();
return (
<>
<div>{counter}</div>
<div>
<Form method="post">
<button type="submit">click</button>
</Form>
</div>
</>
);
}
However, how would the action be triggered in regards to something else like... drag and drop components, where after dropping it should trigger the action post
useSubmit should do what you want.
An example from the docs
import { useSubmit, useTransition } from "remix";
export async function loader() {
await getUserPreferences();
}
export async function action({ request }) {
await updatePreferences(await request.formData());
return redirect("/prefs");
}
function UserPreferences() {
const submit = useSubmit();
const transition = useTransition();
function handleChange(event) {
submit(event.currentTarget, { replace: true });
}
return (
<Form method="post" onChange={handleChange}>
<label>
<input type="checkbox" name="darkMode" value="on" />{" "}
Dark Mode
</label>
{transition.state === "submitting" ? (
<p>Saving...</p>
) : null}
</Form>
);
}

Need to add one input field in file upload component

I have one component in which we have file upload facility. I need to add one additioonal input filed so when user clicks on the upload button one input filed and one file should be sent to server.
since its class component I am not able to use hook. its legacy application.
import axios from 'axios';
import React,{Component} from 'react';
class App extends Component {
state = {
// Initially, no file is selected
selectedFile: null
};
// On file select (from the pop up)
onFileChange = event => {
// Update the state
this.setState({ selectedFile: event.target.files[0] });
};
// On file upload (click the upload button)
onFileUpload = () => {
// Create an object of formData
const formData = new FormData();
// Update the formData object
formData.append(
"myFile",
this.state.selectedFile,
this.state.selectedFile.name
);
// Details of the uploaded file
console.log(this.state.selectedFile);
// Request made to the backend api
// Send formData object
axios.post("api/uploadfile", formData);
};
// File content to be displayed after
// file upload is complete
fileData = () => {
if (this.state.selectedFile) {
return (
<div>
<h2>File Details:</h2>
<p>File Name: {this.state.selectedFile.name}</p>
<p>File Type: {this.state.selectedFile.type}</p>
<p>
Last Modified:{" "}
{this.state.selectedFile.lastModifiedDate.toDateString()}
</p>
</div>
);
} else {
return (
<div>
<br />
<h4>Choose before Pressing the Upload button</h4>
</div>
);
}
};
render() {
return (
<div>
<h3>
File Upload using React!
</h3>
<div>
<input type="file" onChange={this.onFileChange} />
<button onClick={this.onFileUpload}>
Upload!
</button>
</div>
{this.fileData()}
</div>
);
}
}
export default App;
I tried a lot but it is not working properly. if you need I can put the modified code. since its quite messy I put only working code without input field.
Could you please help me to add one input field, please.
Edit 1
Modified Code
import React from 'react';
import axios from 'axios';
class FileUpload extends React.Component {
constructor() {
super();
this.state = {
selectedFile: '',
countryCode: '',
responseArray: [],
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleInput = this.handleInput.bind(this);
}
handleInputChange(event) {
this.setState({
selectedFile: event.target.value,
responseArray: [],
});
}
handleInput(event) {
this.setState({
countryCode: event.target.value,
});
}
handleSubmit() {
if (!this.state.selectedFile) {
alert('Please select The file');
return false;
}
if (!this.state.countryCode) {
alert('Please select The Country Code');
return false;
}
const data = new FormData();
for (let i = 0; i < this.state.selectedFile.length; i++) {
data.append('file', this.state.selectedFile[i]);
}
data.append('countryCode', this.state.countryCode);
console.log(data.countryCode);
let url = process.env.API_URL;
axios.post('http://localhost:8080/file_upload', data, {}).then(
(res) => {
console.log(data);
// this.setState({ responseArray: res.data });
// this.resetFile();
},
(error) => {
alert(error);
}
);
}
resetFile() {
document.getElementsByName('file')[0].value = null;
}
render() {
return (
<form>
<div className="row">
<div className="col-md-12">
<h1>Translation File Upload</h1>
<div className="form-row">
<div className="form-group col-md-8">
<label>Please enter the country code</label>
<input
type="text"
value={this.state.countryCode}
onChange={this.handleInput}
required
/>
</div>
</div>
<div className="form-row">
<div className="form-group col-md-8">
<label>Select File :</label>
<input
type="file"
className="form-control"
multiple
name="file"
onChange={this.handleInputChange}
required
/>
<hr />
</div>
</div>
<br />
<div className="form-row">
<div className="col-md-6">
<button onClick={this.handleSubmit.bind(this)}>Upload </button>
</div>
</div>
<br />
</div>
</div>
</form>
);
}
}
export default FileUpload;
Can you try
<h3>
File Upload using React!
</h3>
<div>
<input type="file" onChange={this.onFileChange} />
<button onClick={this.onFileUpload}>
Upload!
</button>
<input type="text" onChange={this.onInputChange} required>
</div>
and then in your code
inputField: ''
onInputChange = event => {
// Update the state
this.setState({ inputField: event.target.value });
};
// in the formData part
formData.append(
"inputField",
this.state.inputField
);

Input email field onchange not setting string to state if last field

This is really weird, I am setting an email input as a string to state and I can see on react dev tools that it gets sent, but If I try to log it from another function I get empty string, the thing is that If I change the order of the inputs and the email is not the last one then it all works.
import React, { useState, useEffect, useCallback, useContext } from 'react'
import { useDropzone } from 'react-dropzone'
import context from '../provider/context'
import axios from 'axios'
const File = () => {
const { setStage, setProject, project, setUrls, urls, email, setEmail } = useContext(context)
const onDrop = useCallback((acceptedFiles) => uploadFile(acceptedFiles), [project])
const { getRootProps, isDragActive, getInputProps } = useDropzone({ onDrop })
// Set project name
const addProject = (e) => setProject(e.target.value)
// Set email address
const addEmail = (e) => setEmail(e.target.value)
// I got another function then that logs the `email` state,
// but if I do it right after typing on the email input I get empty string.
// If I invert the order, and `project` comes after the email input
// then it displays the email string just fine.
return (
<>
<ul className='list'>
<li>
<label className='label' htmlFor='upload'>
Project's Name
</label>
<input
id='upload'
value={project}
type='text'
name='project'
placeholder='e.g Great Project'
onChange={addProject}
autoFocus
/>
</li>
<li>
<label className='label' htmlFor='email'>
Your email address
</label>
<input
id='email'
type='email'
name='email'
value={email}
placeholder='Email address to send notification to'
onChange={addEmail}
/>
</li>
</ul>
<div className='fileTitle' {...getRootProps()}>
{isDragActive ? <p className='label'>Drop the file here ...</p> : handleResponse()}
<div className='file'>
<div id='drop-area' className={`drop-area ${isDragActive ? 'active' : ''}`}>
<div className={`icon ${response ? response : ''}`}></div>
</div>
<input
{...getInputProps()}
className='inputfile'
id='file'
type='file'
name='locations'
/>
</div>
<br />
<em className='info'>
* Don’t include any headers in the file, just your list of urls with{' '}
<strong>no headers</strong>.
</em>
</div>
</>
)}
export default File
The function that logs the email uses the react-dropzone plugin
// Upload file
const uploadFile = async (file) => {
console.log(email)
const formData = new FormData()
formData.append('urls', file[0])
try {
const options = {
headers: { 'content-type': 'multipart/form-data' },
params: { project, email }
}
const res = await axios.post('/api/upload/', formData, options)
setUrls(res.data.number)
setResponse('success')
setTimeout(() => setStage('process'), 1200)
} catch (err) {
setResponse(err.response.data)
}
}
Doing a simple onclick works fine
const checkEmail = () => {
console.log(email) // This works cause it takes it form the useContext
}
And then on the html
<button onClick={checkEmail}>Click here<button>
In the end I needed to add email as an array dependency to the react-drop zone useCallback so it can register that something has change on that state.
so I changed:
const onDrop = useCallback((acceptedFiles) =>
uploadFile(acceptedFiles), [project])
To
const onDrop = useCallback((acceptedFiles) =>
uploadFile(acceptedFiles), [project, email])
And that is the reason why, when I changed the project field after adding the email it was working.
Many thanks to #NateLevin who helped me find where the problem was at.

This handleSubmit() is not working when I move my Form to a different file

I am following the Scrimba tutorial on React but I decided to move my Form to a new file/component and change the functions to ES6.
Can someone tell me why? Thanks!
Now the handle Submit is not working (it works when the form is rendered in Meme Generator) but I don't know why and it doesn't throw any errors.
import React, { Component } from 'react'
import Form from "./Form"
class MemeGenerator extends Component {
constructor() {
super()
this.state = {
topText: "",
bottomText: "",
randomImg: "http://i.imgflip.com/1bij.jpg",
allMemeImgs: []
}
}
componentDidMount() {
fetch("https://api.imgflip.com/get_memes").then(response => response.json())
.then(response => {
const {memes} =response.data
console.log(memes[2])
this.setState({allMemeImgs: memes})
})
}
handleChange = (event) => {
const {name, value} = event.target
this.setState({[name]: value})
}
handleSubmit = (event) => {
event.preventDefault()
const randNum = Math.floor(Math.random() *
this.state.allMemeImgs.length)
const randMemeImg = this.state.allMemeImgs[randNum].url
this.setState({ randomImg: randMemeImg})
}
render() {
return (
<Form
handleChange = {this.handleChange}
data={this.state}
onSubmit={this.handleSubmit}
/>
)
}
}
export default MemeGenerator
The image is supposed to update to a random image every time the button is clicked. But it doesn't, also the whole page reloads, ignoring the event prevent Default
import React from 'react'
import style from './styles.module.css'
function Form(props) {
return (
<div>
<form className={style.memeForm} onSubmit={props.handleSubmit}>
<input
type="text"
placeholder="Type your top text"
name="topText"
value={props.data.topText}
onChange={props.handleChange}
/>
<input
type="text"
placeholder="Type your bottom text"
name="bottomText"
value={props.data.bottomText}
onChange={props.handleChange}
/>
<button>Generate</button>
</form>
<div className={style.meme}>
<img src={props.data.randomImg} alt="" />
<h2 className={style.top}>{props.data.topText}</h2>
<h2 className={style.bottom}>{props.data.bottomText}</h2>
</div>
</div>
)
}
export default Form
change these lines of code
onSubmit={(event) => props.handleSubmit(event)}
and
<button type='submit'>Generate</button>
<form className={style.memeForm} onSubmit={(event) => props.handleSubmit(event)}>
<input
type='text'
placeholder='Type your top text'
name='topText'
value={props.data.topText}
onChange={props.handleChange}
/>
<input
type='text'
placeholder='Type your bottom text'
name='bottomText'
value={props.data.bottomText}
onChange={props.handleChange}
/>
<button type='submit'>Generate</button>
</form>;

Categories

Resources