import React from "react";
import "./profile.css";
const Notifications = () => {
function changeText() {
themebox.textContent =
"Nice";
}
function changeText2() {
themebox.textContent =
"Fair";
}
function changeText3() {
themebox.textContent = "Aggressive";
}
function changeText4() {
themebox.textContent =
"Threatening";
}
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p className="Selected" onClick={changeText}>
Nice😘
</p>
<p onClick={changeText2}>Fair🕊</p>
<p onClick={changeText3}> Aggressive😈</p>
<p onClick={changeText4}>Threatening🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box" id="themebox"></div>
</div>
</div>
);
};
export default Notifications;
When i click on one of p tags it shows the text that i put in a function which is displayed in the div with classname "theme-box" and id "themebox". Everything seems to work fine, but i get an error in react saying themebox is not defined. Any idea how i can solve that error? :)
There's no variable named themebox in your javascript. Try this out instead, using react to manage state and functions to change the state on click.
// Get a hook function
const {useState} = React;
const Notifications = () => {
const [displayedText, setDisplayedText] = useState("");
const niceText = () => setDisplayedText("Nice");
const fairText = () => setDisplayedText("Fair");
const aggressiveText = () => setDisplayedText("Aggressive");
const threateningText = () => setDisplayedText("Threatening");
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p className="Selected" onClick={niceText}>
Nice😘
</p>
<p onClick={fairText}>Fair🕊</p>
<p onClick={aggressiveText}> Aggressive😈</p>
<p onClick={threateningText}>Threatening🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box" id="themebox">{displayedText}</div>
</div>
</div>
);
};
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Notifications />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
React has it's own way of updating the DOM so it's generally a bad idea to try and manipulate the DOM directly. You should be using and updating state, and then using that state in the JSX.
By doing this you only really need one function which destructures the text content from the clicked element, and sets the state with that text. When the state changes that changed value is reflected in the JSX.
The (new) React documentation site has a good rundown on "how to think in React".
const { useState } = React;
function Example() {
// Initialise the state to an empty string
const [ text, setText ] = useState('');
// When any of the paragraphs is clicked
// destructure the textContent from that element
// and then set the state's new value. `e` is the
// event, and `target` is the element that fired the
// event ie. a paragraph element
function handleClick(e) {
const { textContent } = e.target;
setText(textContent);
}
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p onClick={handleClick}>Nice 😘</p>
<p onClick={handleClick}>Fair 🕊</p>
<p onClick={handleClick}>Aggressive 😈</p>
<p onClick={handleClick}>Threatening 🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box">{text}</div>
</div>
</div>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Related
I'm Turning this Sign in/up Form into a react application, I'm building it through the use of components. I am new to react so I need some help turning vanilla scripts into react components.
Can someone help me code the vanilla js into components (with sliding transition) ?
Vanilla Javascript
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
and React Component:
export const SignForms = () => {
const [ containerActive, setContainerActive] = useState(false);
const signUpButton = () => {
setContainerActive(false);
};
const signInButton = () => {
setContainerActive(true);
};
.....
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-left">
<div className={containerActive ? " right-panel-active" : ""}></div>
<h1 className="font-effect-3d">Come On!</h1>
<p className="font-effect-emboss">Start Your Journey With Us</p>
<button className="ghost" onClick={signInButton} id="signIn" >Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<h1 className="font-effect-3d">No Account?</h1>
<p className="font-effect-emboss">No Problem! Just Sign Up Here</p>
<button className="ghost " onClick={signUpButton} id="signUp">Sign Up</button>
</div>
</div>
</div>
JsFiddle for Vanilla : https://jsfiddle.net/barrogocarlo/dyg9mqn2/ ||
Git Repo for React app: https://gitlab.com/carlobarrogo/sample-forms
You were pretty much there. Keep up !!
Following is the working code, i was able reproduce on my sandbox.
https://codesandbox.io/s/github/devpandya/SamplSignIns/tree/main/?file=/src/SignForms.js
I found 2 issues:
The App.css in vanila.js was different then in your React Code. just copy it from your Vanila Code
use containerActive state to maniplulate classes in container div.
const signUpButton = () => {
setContainerActive(true);
};
const signInButton = () => {
setContainerActive(false);
};
return (
<div className="signForms">
<div
className={`container ${containerActive && "right-panel-active"}`}
id="container"
>
Thats it.. !!!..
Also there was a extra div added in your overlay, just remove it, no use of it
<div className="overlay-panel overlay-left">
**<div className={containerActive ? " right-panel-active" : ""}></div>**
<h1 className="font-effect-3d">Come On!</h1>
I have three files inside a slug. I use slug parameters as directory name.
The problem I am having is everything except the each loop in taglist. For some reason it does not receive the prop tagList. Any help would be appreciated.
index.svelte
<script context="module">
export function preload({ params }, { user }) {
let [id, slug] = [params.id, params.slug];
return { id, slug };
}
</script>
<script>
import Editor from "../../../_components/Editor.svelte";
import Topics from "./Topics.svelte";
import { stores } from "#sapper/app";
export let id;
export let slug;
const { session } = stores();
</script>
<svelte:head>
<title />
</svelte:head>
<div class="editor-page">
<div class="container page">
<div class="row">
<div class="col-md-8 offset-md-2 col-xs-12">
<Topics {id} {slug} />
{#if $session.user}
<Editor />
{/if}
</div>
</div>
</div>
</div>
Topics.svelte
<script>
import { onMount } from "svelte";
import * as api from "api.js";
import "bytemd/dist/index.min.css";
import TagList from "../../../_components/_TagList.svelte";
export let id;
export let slug;
let topics = [];
let title = "";
let tagList = [];
let value = "";
let Viewer = null;
onMount(async () => {
const bytemd = await import("bytemd");
Viewer = bytemd.Viewer;
const response = await api.get(
`t/${id}/${slug}`,
localStorage.getItem("jwt")
);
console.log(response);
if (response.topic) {
topics = response.topic;
title = response.title;
value = topics[0].description;
for(let i= 0; i < response.tags.length; i++) {
tagList.push(response.tags[i]);
}
}
});
</script>
<div>
<h3>{title}</h3>
<hr/>
<svelte:component this={Viewer} {value} />
<TagList {tagList} />
</div>
_TagList.svelte
<script>
export let tagList;
console.log(tagList);
</script>
<ul>
{#each tagList as tag}
<p>hello</p>
<li>{tag.name}</li>
{/each}
</ul>
In Svelte, updates are only triggered with an assignment.
In your case that means that when the component is rendered it will render an empty taglist (tagList = []).
Now in onMount you do taglist.push, but as said earlier, this doesn't trigger an update (remember that this function is called after the component has mounted) because it is not an assignment.
There are four ways to fix it in your case:
after the for loop you do tagList = tagList, this is an assignment and will trigger the update.
instead of doing the for loop use a mapping tagList = response.tags.map(tag => tag)
instead of doing the for loop you spread the tags into the taglist tagList = [...response.tags]
considering you don't do anything with the tags anyway, and tagList is empty and you don't seem to have any other way to update, just assign the tags to it directly tagList = response.tags
Of course your code might be simplified, if you actually do something with each tag before adding it to the list case 3 and 4 are not good options, for that scenario I would use the map option
Hello I am new to React and building a quote generator. I want to pull out one quote at a time from my array and show it on the screen, however I can only seem to output each quote to the console.
I have:
1.Created an on click handler and function so that when the user clicks my quote array is targeted.
2. In this function I have created a variable to hold my random array index
3. I have console.logged the array index to see if every time the user clicks it the quote appears.
Component and function and click handler, as you can see the Quote Component should return the quote from the array in my opinion but nothing happens:
class Card extends Component {
state = {
quotes: ['"A dream doesn\'t become reality through magic; it takes sweat, determination and hard work."','"You GOT this!"','"To be or not to be that is the question"'];
changeQuoteHandler = (event) => {
const quotes = [...this.state.quotes];
const arrayIndex = quotes[Math.floor(Math.random() * quotes.length)]
console.log(arrayIndex);
this.setState({
quotes: quotes
})
};
render(){
return (
<div className="Card">
<div>
<h2>Random Quote Generator</h2>
<Quote className="QuoteStyle" quote={this.state.quotes.arrayIndex}/>
</div>
<div className="Flex">
<div>
<NewQuoteButton onClick={this.changeQuoteHandler}/>
</div>
</div>
</div>
)
}
};
export default Card;
Quote Componenet :
import React from 'react';
const Quote = (props) => {
return(
<p>{props.quote}</p>
)
};
export default Quot
I would like to print one quote at a time to the screen on click.
You are so close. You can store the arrayIndex that you generate in the state and use it to display the quote. The code would look like something below
class Card extends Component {
state = {
quotes: ['"A dream doesn\'t become reality through magic; it takes sweat, determination and hard work."','"You GOT this!"','"To be or not to be that is the question"'],
selectedIndex: 0,
}
changeQuoteHandler = (event) => {
const quotes = [...this.state.quotes];
const arrayIndex = Math.floor((Math.random() * 10) % quotes.length);
this.setState({
quotes: quotes,
selectedIndex: arrayIndex,
});
};
render(){
return (
<div className="Card">
<div>
<h2>Random Quote Generator</h2>
<Quote className="QuoteStyle" quote={this.state.quotes[this.state.selectedIndex]}/>
</div>
<div className="Flex">
<div>
<NewQuoteButton onClick={this.changeQuoteHandler}/>
</div>
</div>
</div>
)
}
};
export default Card;
I need to find the length of child element divs
<div className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
</div>
Here is my code. Need to find no of 'intent' elements
You can use callback ref.
ref={(ele) => this.myEle = ele
put callback ref on parent node which length or child count you want.
return (<div style={styles} ref={(ele) => this.myEle = ele}>
<div >Hello World</div>
<h2>Start editing to see some magic happen {'\u2728'}</h2>
</div>);
Use componentDidMount or componentDidUpdate life cycle to get the length.
componentDidMount(){
console.log(this.myEle.children.length); //2
}
Working React#codesandbox demo
You can use ReactDOM.findDOMNode, even-though the documentation encourages using ref.
DEMO
You need to put ref on parent node.
<div ref="intentContainer" className="intentContainer"></div>
Use the following code in our componentDidMount method.
componentDidMount(){
// get this intentContainer using ref (Its your parent)
var intentContainer = this.refs.intentContainer;
// this will return the count of all childrens
var childrenCount = this.refs.intentContainer.children.length;
// get the count by particular class name from parent dom
var countByClass = ReactDOM.findDOMNode(intentContainer).getElementsByClassName('intent').length;
}
And your render method like as follows,
render() {
return (
<div ref="intentContainer" className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
</div>
);
}
For more help please check to here and here.
Hoeps this will help you !!
import React, { Component } from "react";
export default class SampleComponent extends Component {
intentCount(){
console.log(document.querySelectorAll('.intent').length)
}
render() {
return (
<div className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
<div className="intent">
</div>
<button onClick={this.intentCount}>Intent Count</button>
</div>
);
}
}
This should work :) ..
Explanation to why this is not a duplicate: My code is already working, I have included as a comment. The question is why the this context change when I include it to click handler function.
I'm attempting a calculator project in React. The goal is to attach onclick handlers to number buttons so the numbers are displayed on the calculator display area. If the handler is written directly to render method it is working, however, if I'm trying from the ComponentDidMount I get an error this.inputDigit is not a function. How do I bind this.inputDigit(digit) properly?
import React from 'react';
import './App.css';
export default class Calculator extends React.Component {
// display of calculator initially zero
state = {
displayValue: '0'
}
//click handler function
inputDigit(digit){
const { displayValue } = this.state;
this.setState({
displayValue: displayValue+String(digit)
})
}
componentDidMount(){
//Get all number keys and attach click handler function
var numberKeys = document.getElementsByClassName("number-keys");
var myFunction = function() {
var targetNumber = Number(this.innerHTML);
return this.inputDigit(targetNumber); // This is not working
};
for (var i = 0; i < numberKeys.length; i++) {
numberKeys[i].onclick = myFunction;
}
}
render() {
const { displayValue } = this.state;
return (
<div className="calculator">
<div className="calculator-display">{displayValue}</div>
<div className="calculator-keypad">
<div className="input-keys">
<div className="digit-keys">
{/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}}
<button className="number-keys">0</button>
<button className="number-keys1">1</button>
<button className="number-keys">2</button>
<button className="number-keys">3</button>
<button className="number-keys">4</button>
<button className="number-keys">5</button>
<button className="number-keys">6</button>
<button className="number-keys">7</button>
<button className="number-keys">8</button>
<button className="number-keys">9</button>
</div>
</div>
</div>
</div>
)
}
}
Thats because you are writing it inside a function which is not bound,
Use
var myFunction = function() {
var targetNumber = Number(this.innerHTML);
return this.inputDigit(targetNumber);
}.bind(this);
or
const myFunction = () => {
var targetNumber = Number(this.innerHTML);
return this.inputDigit(targetNumber);
}
After this you need to bind the inputDigit function as well since it also uses setState
//click handler function
inputDigit = (digit) => {
const { displayValue } = this.state;
this.setState({
displayValue: displayValue+String(digit)
})
}
Since you want to use the button text as well, in that case you should use a separate variable in place of this to call the inputDigit function like
class Calculator extends React.Component {
// display of calculator initially zero
state = {
displayValue: '0'
}
//click handler function
inputDigit(digit){
const { displayValue } = this.state;
this.setState({
displayValue: displayValue+String(digit)
})
}
componentDidMount(){
//Get all number keys and attach click handler function
var numberKeys = document.getElementsByClassName("number-keys");
var that = this;
var myFunction = function() {
var targetNumber = Number(this.innerHTML);
console.log(targetNumber);
return that.inputDigit(targetNumber); // This is not working
};
for (var i = 0; i < numberKeys.length; i++) {
numberKeys[i].onclick = myFunction;
}
}
render() {
const { displayValue } = this.state;
return (
<div className="calculator">
<div className="calculator-display">{displayValue}</div>
<div className="calculator-keypad">
<div className="input-keys">
<div className="digit-keys">
{/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}
<button className="number-keys">0</button>
<button className="number-keys">1</button>
<button className="number-keys">2</button>
<button className="number-keys">3</button>
<button className="number-keys">4</button>
<button className="number-keys">5</button>
<button className="number-keys">6</button>
<button className="number-keys">7</button>
<button className="number-keys">8</button>
<button className="number-keys">9</button>
</div>
</div>
</div>
</div>
)
}
}
ReactDOM.render(<Calculator/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Bind it in the constructor
constructor(props) {
super(props);
this.inputDigit = this.inputDigit.bind(this);
}