How to upload image with preview in react js - reactjs

I have a reactjs application. I would like to know how to upload image with preview. Please advise.

you must read this mdn document about FileReader.
And then, based on your understand, you can apply like this.
export default () => {
const [preview, setPreview] = useState(null);
const fileHandler = evt => {
const f = evt.target.files[0];
if (f) {
const reader = new FileReader();
reader.onload = ({ target: { result } }) => {
setPreview(result);
};
reader.readAsDataURL(f); // you can read image file as DataURL like this.
} else {
setPreview(null);
}
};
return (
<div>
<input
type="file"
accept="image/*"
onChange={fileHandler}
/>
{ preview && <img src={preview} /> }
</div>);
}

The following illustrated code example is a part of my project.
As long as if you aren't following strict react pratices then this should work really well. You can change the styling as per your needs.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
const imageHandler = () => {
const inpFile = document.getElementById('inpFile');
const previewContainer = document.getElementById('imagePreview');
const previewImage = previewContainer.querySelector('.image-preview__image');
const previewDefaultText = previewContainer.querySelector('.image-preview__default-text');
inpFile.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
previewDefaultText.style.display = 'none';
previewImage.style.display = 'block';
reader.addEventListener('load', function() {
previewImage.setAttribute('src', this.result);
});
reader.readAsDataURL(file);
} else {
previewDefaultText.style.display = null;
previewImage.style.display = null;
previewImage.setAttribute('src', '');
}
});
};
return (
<div>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<div className="login">
<div className="reg-container">
<div className="profile-pic">
Add your Profile Picture:
<div className="add-picture">
<div className="image-preview" id="imagePreview">
<div className="card-image" />
<img alt="" className="image-preview__image" />
<span className="image-preview__default-text" />
</div>
<input
onClick={imageHandler}
type="file"
name="inpFile"
id="inpFile"
accept="image/*"
/>
<div className="label-holder">
<label className="image-upload" for="inpFile">
<i className="material-icons">add_photo_alternate</i>
Choose your Photo
</label>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
and obviously the styling file App.css
#import url('https://fonts.googleapis.com/css?family=Lato|Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
}
.profile-pic {
font-family: 'Varela Round', sans-serif;
text-align: center;
padding: 1rem;
padding-top: 0;
padding-bottom: 0;
font-weight: bold;
font-size: 1.5rem;
}
/* ============================== */
.add-picture{
margin: auto;
font-size: 1rem;
display: flex;
text-align: center;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: 'Lato', sans-serif;
}
.image-preview{
width: 120px;
min-height: 150px;
border: 5px solid black;
margin-top: 15px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #000;
outline: none;
z-index: ;
}
.image-preview__image{
display: none;
width: 100%;
height: 150px;
display:block;
object-fit: cover;
z-index: -11;
}
span{
/* background-image: url("../blank_user.webp"); */
width: 120px;
height: 150px;
background-size: cover;
background-position: center;
z-index: -9;
position: absolute;
border-radius: 15px;
outline: none;
}
#inpFile[type="file"]{
display:none;
margin-top: 20px;
}
.label-holder{
width: 200px;
height: 50px;
margin-top: 1rem;
}
.image-upload{
color: white;
background-color: black;
border: 1px solid #000;
display: inline-block;
padding: 6px 12px;
cursor: pointer;
font-family: 'Lato', sans-serif;
display: flex;
justify-content: center;
border-radius: 50px;
}
.description {
font-family: 'Varela Round', sans-serif;
text-align: center;
padding: 1rem;
padding-top: 0;
font-weight: bold;
font-size: 1.5rem;
}
.description textarea{
font-family: 'Lato', sans-serif;
font-size: 1rem;
background: none;
width: 350px;
height: 100px;
border: 2px solid black;
border-radius: 10px;
outline: none;
text-align: center;
}
#media screen and (max-width:550px){
.description textarea{
width: 260px;
}
}
Consider watching this Tutorial and other online article
you can also add the state management to the <input/>

Related

setState and changing style conditionally don't work together

I got some issues with the following code:
//FIRST PAGE
import React from "react";
import './index.css'
import Boxx from "./Boxx";
export default function WindowZero (prop){
//
// FETCH COMING DATA
const fetchData = async () =>{
const data = await prop.data
return data
}
// FUNCTION FIRST PAGE
function RenderZero (){
return (<div className="Zero--">
<h1 className="Zero--h" > Welcome to Quizzly</h1>
<p className="Zero--p">click the start button to start</p>
<button className="Zero--start" onClick={()=>{ prop.setZero()}}>Quiz Me</button>
</div>)
}
// CONDITIONAL RENDERING
if(prop.zero){
return <RenderZero/>
}
else{
return <Boxx dataI={fetchData()}/>
}
}
This is the first page. It supposes to show the user a button when it was clicked, it renders the other page which shows a page of questions:
// THE OTHER PAGE
import React from "react";
import './index.css'
import {useState, useEffect} from 'react'
export default function Boxx (prop) {
// STATES & VARIABLES INITIALIZAITION
var sAnswersA = []
for(let i = 0; i<5; i++){
sAnswersA.push({id:i, value:'', correct:null})
}
var [selectedAnswers,setSelectedAnswers] = useState(sAnswersA)
var [truth,setTruth] = useState(true)
var [comingData, setComingData] = useState([])
// FETCHING FUNCTION::
let fetching = async()=>{
let x = await prop.dataI;
return x;
}
// USEEFFECT & FETCHE INSIDE::
useEffect(()=>{
fetching().then((result)=>{
var array = result.slice()
if(array[0].incorrect_answers.length != 4){
array.map(item=>{
item.incorrect_answers.push(item.correct_answer)
shuffle(item.incorrect_answers)
})}
for(let i = 0; i< array.length; i++){
array[i]= {...array[i], id:i}
}
setComingData(array)
})
},[])
// SHUFFLE FUNCTION::
function shuffle(array) {
let currentIndex = array.length, randomIndex ;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
// EVENTLISTENERS::
const handler = (e,obj) =>{
var targetD = e.target
console.log(targetD)
console.log(obj)
obj.incorrect_answers.map(item=>{
if(item===targetD.innerText){
console.log('true')
let nodess = targetD.parentNode.childNodes;
nodess.forEach(i=>{
if(i.classList.contains('selected-')){
i.classList.remove('selected-')
}
})
targetD.classList.add('selected-')
}
})
}
// FUNCTION TO SUM ANSWERS::
const sumAnswers = (e,obj) =>{
// console.log(selectedAnswers[0].id)
setSelectedAnswers(prev=>{
return prev.map(it=>{
return obj.id === it.id ? {...it, value:e.target.innerText} : {...it}
})
})
}
// SHUFFLE DATA === Done
// ADD EVENT LISTENERS; STYLES; SUBMIT BTN; COLLECT ANSWERS; CHECK ANSWERS; SHOW RESULT;
//console area...
console.log(selectedAnswers)
// FUNCTION RUN = CREATE THE DOM ELEMENTS::
const Run = () => {
return comingData.map(item=>{
return(
<div key={Math.random()*9} className="questionBody--" id={item.id}>
<p className="qB--question">{item.question}</p>
<div className="answers--" id={item.id}>
<p className="qB--answer" id="0" onClick={(e)=>handler(e,item)}>{item.incorrect_answers[0]}</p>
<p className="qB--answer" id="1" onClick={(e)=>handler(e,item)}>{item.incorrect_answers[1]}</p>
<p className="qB--answer" id="2" onClick={(e)=>handler(e,item)}>{item.incorrect_answers[2]}</p>
<p className="qB--answer" id="3" onClick={(e)=>handler(e,item)}>{item.incorrect_answers[3]}</p>
</div>
</div>
)
})
}
return(<Run/>)
}
here is my App.js:
import './App.css';
import WindowZero from './windowZeroComponent';
import React, {useState,useEffect} from 'react';
function App() {
var [zero, setZero] = useState(true)
//
var [dataI, setDataI] = useState([])
//
useEffect(()=>{
fetcData()
},[])
const fetcData = async () =>{
const getData = await fetch('https://opentdb.com/api.php?amount=5&category=27&type=multiple')
const getDataJson = await getData.json()
setDataI(getDataJson.results)
}
return (
<div className='App--'>
hi
<WindowZero data = {dataI} zero={zero} setZero = {()=>setZero(prev=>!prev)}/>
</div>
);
}
export default App;
CSS file:
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
*{
box-sizing:border-box;
padding: 0 ;
margin: 0 ;
}
/* */
.Zero--{
background-image: linear-gradient(#37f,#3af);
height:100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 10% 5%;
}
.Zero--h{
text-transform: uppercase;
font-size: 28px;
font-weight: 500;
color: #f0f0ff;
padding: 12px;
}
.Zero--p{
font-size: 20px;
font-weight: 300;
padding: 8px;
color: #f0f0f0;
}
.Zero--start{
border: none;
padding: 10px 16px;
margin: 4px;
font-size: 22px;
font-weight: 700;
text-transform: uppercase;
border-radius: 16px;
background-color: #0ff;
color: #333333;
cursor: pointer;
}.Zero--start:hover{
transition:all ease-in-out 400ms;
transform: scale(1.11);
}
/* */
.questionBody--{
display: flex;
flex-direction: column;
background-color: transparent;
border-bottom: 1px solid #a0a0a0;
margin: 30px 0px;
}
.qB--question{
color: #007;
outline-color: #333333;
font-size: 26px;
font-weight: 600;
padding: 4px;
margin-left: 12px;
text-shadow: 0px 0px 1px #111;
}
.answers--{
display: flex;
flex-direction: row;
background-color: transparent;
}
.qB--answer{
padding: 0px 16px;
margin: 12px;
border-radius: 10px;
border:1px solid #999;
text-align: center;
/* color: #22f; */
font-size: 18px;
font-weight: 500;
text-shadow: 0px 0px 1px #111;
display: flex;
justify-content: center;
align-items: center;
}.qB--answer:hover{
transition: all ease-in 400ms;
background-color: #007;
color: #fff;
cursor: pointer;
}
/* */
.Main--{
padding: 25px 15%;
min-height: 100vh;
background-image: url('./background--.jpg');
background-repeat: no-repeat;
background-size: cover;
}
.submit--{
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: center;
}
.submit--button{
padding: 2px 26px;
background-color: #007;
color: #fff;
font-size: 20px;
font-weight: 600;
border-radius: 12px;
margin: 0px 15px;
border: none;
}.submit--button:hover{
transition: all ease-in 400ms;
color: #007;
cursor:pointer;
background-color: #fff;
}
.conclusion--{
font-size:18px;
font-weight: 600;
}
.selected-{
background-color:#0ff;
color: #700;
}
My problem is that on the Other page (Boxx.js), specifically in //EVENENTLISTENERS => handler function: I'm trying to put sumAnswers(e,obj){which collects the clicked answers and add it to a state} inside of it, but when I do, the handler() stops adding the style to the clicked answer. I tried to put both of them inside of a function that runs after clicking on each answer but that didn't work too.
hope someone could help.
thx for reading, sorry for my English.

how can i move image a very little bit up and add text below it { note i am talking about the highlighted profile image with blue }

how can i move image a very little bit up and add text below it { note i am talking about the highlighted profile image with blue } [image here][1] also see my code and tell every step to do that i have tired margin button but it didn't work
`import { Header } from "../../features/theme/Header";
import styles from "./Home.module.css";
import { useAppSelector } from "../../app/hooks";
import { Feed } from "../../features";
export function Home(): JSX.Element {
const { currentUserImage } = useAppSelector((state) => state.currentUser);
return (
<div className={styles.home}>
<Header page="Home" />
<div className={styles.tweetField}>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
</div>
<div>
<div>
</div>
</div>
</div>
<Feed />
</div>
);
}
my css code
.home{
border-right: solid 0.2px var(--border-color);
}
.homeHeader{
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
border-bottom: solid 0.2px var(--border-color);
font-size: 1.2rem;
font-weight: bold;
}
.homeHeader button{
border: none;
background: none;
font-size: 1.3rem;
color: var(--theme-page-text);
}
.tweetField{
display: flex;
margin-top: 1rem;
border-bottom: solid 0.2px var(--border-color);
}
.userAvatar{
outline: none;
width: 3rem;
height: 3rem;
border-radius: 50%;
margin-left: 1rem;
background: #fff;
}
.userAvatar img{
width: 3rem;
height: 3rem;
border-radius: 50%;
object-fit: cover;
background: #fff;
}
.tweetActions{
width: 100%;
margin: 1rem;
}
.tweetActions span{
font-size: 1.3rem;
color: var(--light-text-color);
}
.tweetActions div{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 1rem;
}
.tweetActions button:first-child{
border: none;
background: none;
outline: none;
color: var(--primary-color);
font-size: 1.2rem;
}
.tweetActions button:last-child{
border: none;
outline: none;
color: #fff;
background: var(--primary-color);
opacity: 0.5;
font-size: 1rem;
font-weight: bold;
padding: 0.5rem 1.2rem;
border-radius: 2rem;
}
image here =
[1]: https://i.stack.imgur.com/JpZKd.png

ow can i move image a very little bit up and add text below it { note i am talking about the highlighted profile image with blue }

how can i move image a very little bit up and add text below it { note i am talking about the highlighted profile image with blue }also see my code and tell every step to do that i have tired margin button but it didn't work pls tell how to do pls also see the image image here
`import { Header } from "../../features/theme/Header";
import styles from "./Home.module.css";
import { useAppSelector } from "../../app/hooks";
import { Feed } from "../../features";
export function Home(): JSX.Element {
const { currentUserImage } = useAppSelector((state) => state.currentUser);
return (
<div className={styles.home}>
<Header page="Home" />
<div className={styles.tweetField}>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
</div>
<div>
<div>
</div>
</div>
</div>
<Feed />
</div>
);
}
my css code
.home{
border-right: solid 0.2px var(--border-color);
}
.homeHeader{
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
border-bottom: solid 0.2px var(--border-color);
font-size: 1.2rem;
font-weight: bold;
}
.homeHeader button{
border: none;
background: none;
font-size: 1.3rem;
color: var(--theme-page-text);
}
.tweetField{
display: flex;
margin-top: 1rem;
border-bottom: solid 0.2px var(--border-color);
}
.userAvatar{
outline: none;
width: 3rem;
height: 3rem;
border-radius: 50%;
margin-left: 1rem;
background: #fff;
}
.userAvatar img{
width: 3rem;
height: 3rem;
border-radius: 50%;
object-fit: cover;
background: #fff;
}
.tweetActions{
width: 100%;
margin: 1rem;
}
.tweetActions span{
font-size: 1.3rem;
color: var(--light-text-color);
}
.tweetActions div{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 1rem;
}
.tweetActions button:first-child{
border: none;
background: none;
outline: none;
color: var(--primary-color);
font-size: 1.2rem;
}
.tweetActions button:last-child{
border: none;
outline: none;
color: #fff;
background: var(--primary-color);
opacity: 0.5;
font-size: 1rem;
font-weight: bold;
padding: 0.5rem 1.2rem;
border-radius: 2rem;
}
wewaewavresrvesgrefesfvesfvesfrervesrservesrves

Pushing Sign Up & Login buttons to bottom of sidebar

I am trying to recreate this design:
Click to view
However, the below is currently occurring.
Click to view
I am trying to push the SignUp and Login buttons to the bottom of the sidebar to match the first image. Am I missing a CSS class that would allow me to do so, or would this be a JS configuration? Hope I have not overlooked something basic that would allow me to achieve this state.
Sidebar.js
import React from "react";
import "../App.css";
import { SidebarData } from './SidebarData'
import Logo from './Logo.svg'
import { Login } from './Login'
import { SignUp } from './SignUp'
function Sidebar() {
return (
<div className="Sidebar">
<div className="Header">
<div><img src = {Logo} alt='Logo’ className='Logo’ /></div>
</div>
<div class="line-break" />
<ul className="SidebarList">
{SidebarData.map((val, key) => {
return (
<li
key={key}
className="row"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="icon">{val.icon}</div> <div id="title">{val.title}</div>
</li>
);
})}
</ul>
<div class="line-break" />
<div className="footer">
<ul className= "SidebarList">
{Login.map((val, key) => {
return (
<li
key={key}
className="Login"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="title">{val.title}</div>
</li>
)}
)}
</ul>
<ul className= "SidebarList">
{SignUp.map((val, key) => {
return (
<li
key={key}
className="SignUp"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="title">{val.title}</div>
</li>
)}
)}
</ul>
</div>
</div>
Here is CSS
.App {
width: 100vw;
height: 100vh;
}
body {
margin: 0;
padding: 0;
}
.Sidebar {
height: 100%;
width: 300px;
background-color: white;
border-right: 1px solid #F0F4FB;
padding-left: 15px;
box-sizing: border-box;
}
.SidebarList {
height: auto;
width: 100%;
padding-left: 15px;
font-size: 18px;
border: 2px #FD954E;
box-sizing: border-box
}
.SidebarList .row {
width: 100%;
height: 50px;
background-color: white;
list-style-type: none;
margin: 0%;
padding-bottom: 15px;
display: flex;
color: #A7ACB6;
justify-content: center;
align-items: center;
font-family: Arial, Helvetica, sans-serif;
}
.SidebarList .row:hover {
cursor: pointer;
background-color: #E7E7E7 ;
}
.SidebarList #active {
background-color: white;
color: #FD954E
}
.SidebarList .Login {
background-color: white;
color: #FD954E;
width: 90%;
height: 5vh;
right: 1596px;
top: 958px;
border: 1px solid #FD954E;
box-sizing: border-box;
border-radius: 19.5px;
text-align: center;
font-family: Arial, Helvetica, sans-serif
}
.SidebarList .SignUp {
width: 90%;
height: 5vh;
right: 1596px;
top: 1011px;
background: #FD954E;
border-radius: 19.5px;
border: none;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
}
.row #icon {
flex: 30%;
display: grid;
place-items: center;
transform: scale(1.2)
}
.row #title {
flex: 70%;
}
.Logo {
padding-left: 25px;
padding-top: 25px;
padding-bottom: 30px;
width: 55%;
}
.line-break {
height: 1px;
width: 100%;
background-color: #F0F4FB;
}
ul.nav {
list-style-type: none;
padding: 20px 0 0 40px;
list-style-type: none;
}
ul.nav li {
margin-bottom: 14px;
list-style-type: none;
}
ul.nav li:last-child {
margin-bottom: 0;
list-style-type: none;
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 0;
}
.footer button {
padding: 6px 0;
width: 80%;
margin-bottom: 14px;
}
.footer button:last-child {
margin-bottom: 0;
}
.header .Logo {
height: 40px;
width: 200px;
background-color: grey;
margin: 20px;
}
Without seeing the source for the entire page and not just a couple of the buttons, it is impossible to say for sure, but my guess would be the following is causing your problem:
.Sidebar {
height: 100%;
...
}
Setting height: 100% will only tell the sidebar to take up 100% of the space it needs for its content (or 100% of the height of its bounding container, depending on the display properties of both). I would recommend changing it to this to solve your problem:
.Sidebar {
min-height: 100vh;
...
}

How do you embed a BTCPay button in React?

When creating a pay button on the BTCPay dashboard, it gives you code that looks like:
<script>if(!window.btcpay){ var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.src='https://btcpayjungle.com/modal/btcpay.js'; script.type = 'text/javascript'; head.append(script);}function onBTCPayFormSubmit(event){ var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { if(this.status == 200 && this.responseText){ var response = JSON.parse(this.responseText); window.btcpay.showInvoice(response.invoiceId); } } }; xhttp.open("POST", event.target.getAttribute('action'), true); xhttp.send(new FormData( event.target ));}</script><style type="text/css"> .btcpay-form { display: inline-flex; align-items: center; justify-content: center; } .btcpay-form--inline { flex-direction: row; } .btcpay-form--block { flex-direction: column; } .btcpay-form--inline .submit { margin-left: 15px; } .btcpay-form--block select { margin-bottom: 10px; } .btcpay-form .btcpay-custom { display: flex; align-items: center; justify-content: center; } .btcpay-form .plus-minus { cursor:pointer; font-size:25px; line-height: 25px; background: #DFE0E1; height: 30px; width: 45px; border:none; border-radius: 60px; margin: auto 5px; display: inline-flex; justify-content: center; } .btcpay-form select { -moz-appearance: none; -webkit-appearance: none; appearance: none; color: currentColor; background: transparent; border:1px solid transparent; display: block; padding: 1px; margin-left: auto; margin-right: auto; font-size: 11px; cursor: pointer; } .btcpay-form select:hover { border-color: #ccc; } #btcpay-input-price { -moz-appearance: none; -webkit-appearance: none; border: none; box-shadow: none; text-align: center; font-size: 25px; margin: auto; border-radius: 5px; line-height: 35px; background: #fff; } </style>
<form method="POST" onsubmit="onBTCPayFormSubmit(event);return false" action="https://btcpayjungle.com/api/v1/invoices" class="btcpay-form btcpay-form--block">
<input type="hidden" name="storeId" value="..." />
<input type="hidden" name="jsonResponse" value="true" />
<input type="hidden" name="price" value="0.01" />
<input type="hidden" name="currency" value="BTC" />
<input type="image" class="submit" name="submit" src="https://btcpayjungle.com/img/paybutton/pay.svg" style="width:209px" alt="Pay with BtcPay, Self-Hosted Bitcoin Payment Processor">
</form>
to copy and paste into your website. The main problem is it that code uses script and style tags which aren't allowed in React's JSX sytax. So how do you embed the button in a React Website?

Resources