How to change the checked property in a checkbox? - html

I have a state called ListItems and I wish to display them as checked if the value is present in another state array called filteredListItems. I have created a callback function but this doesn't seem to work. How do I go on about this?
import React, {useState, useRef} from 'react'
import { connect, useDispatch, useSelector, useStore} from 'react-redux';
import { setEnable} from "../actions";
import './Settings.css'
function Settings(props){
const dispatch=useDispatch();
const [listItems,setListItems]=useState(props.defaultenableVal);
const [filteredListItems,setFilteredListItems]=useState(props.defaultenableVal);
const dragItem = React.useRef();
const dragOverItem = React.useRef();
const handleSort=()=>{
let _listItems=[...listItems];
const draggedItemContent=_listItems.splice(dragItem.current,1)[0];
_listItems.splice(dragOverItem.current,0, draggedItemContent);
dragItem.current=null;
dragOverItem.current=null;
setListItems(_listItems);
}
return(
<div className='container'>
<h3>Dimensions and Metrics</h3>
{
listItems.map((item,index)=>{
return (
<div
key={index}
draggable
onDragStart={(e)=>dragItem.current=index}
onDragEnter={(e)=>dragOverItem.current=index}
onDragEnd={handleSort}
onDragOver={(e)=>e.preventDefault()} >
<input id={index} name={item} type='checkbox'
checked={(()=>{
if(filteredListItems.includes(item)){
return true
}
else{
return false
}
})} />
<label htmlFor={index} >{item}</label>
</div>
)
})
}
</div>
)
}
export default Settings;
The value of props.defaultEnableVal is ['Clicks', 'AD Requests', 'AD Responses', 'Impressions', 'Revenue', 'Fill Rate', 'CTR'].
The check does not appear on the checkbox and it doesn't seem to be accepting check input when I click on it.

Related

why state is not initializing with given value?

latest value is coming from props, but when it is added as the initial value for state it is not showing up.
import React, { useRef, useState } from "react";
//import config from "../../../../../../config";
//import { getAuthToken } from "../../../../../utils/auth";
import styles from "./ContentRowPrice.module.css";
const ContentRowPrice = (props) => {
const [priceInput, setPriceInput] = useState(props.price);
// const priceInput = useRef();
// const handleBlur = () => {
// const price = parseFloat(priceInput.current.value);
// if (props.price === price) {
// } else {
// props.onPaywallChange(price);
// }
// };
const classes = styles["contentrowprice-input"];
return (
<>
<span>{props.price}</span>
<span>{priceInput}</span>
<input
id={`paywall_${props.price}_${props.id}`}
type="number"
min="0"
step="0.01"
// ref={priceInput}
// defaultValue={props.price}
value={priceInput}
className={classes}
// onBlur={handleBlur}
/>
</>
);
};
export default ContentRowPrice;
one Thing that I realized that the value 10 is actually coming from input that was previously in the place of the above input.
The first render of a React component is with empty values, this is the moment when react component creates component and a state with useState hook.
When you assign it in useState, it will not change in second (or later) re-renders without a useEffect hook.
useEffect(() => {
setPriceInput(props.price);
}, [props.price]);
More about this problem, you can read here:
https://medium.com/#digruby/do-not-use-props-as-default-value-of-react-usestate-directly-818ee192f454

How to implement multiple API in one component

i stuck in a project where i have to implement JSON Place Holder Post API and JSON Place Holder Comment API both API in a particular component.Actually my task is build a project like a facebook post component where user can post and comment. I implemented Post API successfully but i couldn't find any solution to use comment API. I did all thing but it's not show in my Home component.
How can i implement comment api in my home component
my console said it present but i couldn't show this
This is Home.js File
import React, { useEffect, useState } from 'react';
import Post from '../Post/Post';
import Comment from '../Comment/Comment';
import './Home.css';
const Home = () => {
const [post,setPost] = useState([]);
const [comment,setComment] = useState([]);
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res=>res.json())
.then(data=>setPost(data))
},[])
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/comments')
.then(res=>res.json())
.then(data=>setComment(data))
},[])
return (
<div>
<div>
{
post.map(post=><Post post={post}></Post>)
}
</div>
<div className="main-body">
{
comment.map(comment=><Comment comment={comment}></Comment>)
}
</div>
</div>
);
};
export default Home;
This comment.js File
import React from 'react';
const Comment = (props) => {
const {name,email} = props.comment.name;
console.log(props.comment);
return (
<div>
{name}
{email}
</div>
);
};
export default Comment;
This is post.js File
import React from 'react';
import './Post.css';
const Post = (props) => {
const {title,body} = props.post;
return (
<div className="body-style">
<h1 className="name">{title}</h1>
<p>{body}</p>
</div>
);
};
export default Post;
Please help me I need solution
The structure is incorrect, in order to do that, comment should be children of post, and home will pass data to the post. Since you fetch data from 2 difference API, you need to combined it into 1 source and pass that down.
Home.js
import React, { useEffect, useState } from 'react';
import Post from '../Post/Post';
import './Home.css';
const Home = () => {
const [post,setPost] = useState([]);
const [comment,setComment] = useState([]);
const [ info, setInfo ] = useState([]);
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res=>res.json())
.then(data=>setPost(data))
},[])
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/comments')
.then(res=>res.json())
.then(data=>setComment(data))
},[])
//Function to combine post and comment base on ID
const merge = (post, comment) => {
const temp = [];
post.forEach((x) => {
comment.forEach((y) => {
if (x.id === y.id) {
let cName = y.name;
let cEmail = y.email;
let cBody = y.body;
temp.push({ ...x, cName, cEmail, cBody });
}
});
});
return temp;
};
useEffect(
() => {
setInfo(merge(post, comment));
console.log(info);
},
[ post, comment ]
);
return (
<div>
{info.map((each) => <Post key={each.id} data={each} />)}
</div>
);
};
export default Home;
Post.js
import React from 'react';
import Comment from './Comment';
const Post = (props) => {
const { title, body, cEmail, cName } = props.data;
return (
<div className="body-style">
<h1 className="name">{title}</h1>
<p>{body}</p>
<Comment email={cEmail} name={cName} />
</div>
);
};
export default Post;
Comment.js
import React from 'react';
const Comment = ({ name, email }) => {
return (
<div>
{name}
{email}
</div>
);
};
export default Comment;

In React, is it possible to store a ref in a context?

I need global app-wide access to a VideoElement to play it on user events on browsers like Safari and was wondering if storing the VideoElement in a context would be the best way to do that. I programmatically play my video through a redux action and in Safari that is not possible unless it has been played once through a user triggered event (like a click)
Is it possible to store an element (ref) within a context? The VideoElement will be then rendered within the component which I want to have my video, and then other components will also have access to the context and be able to call functions such as usePlayVideo that based on the context's state, will either call videoElement.play() if this is the first time the video is being played, or dispatch the redux action to play the video programmatically otherwise
It is possible to store a ref into context! You need to create a context at first. Then you need to pass value to the context provider and create a ref object using useRef hook. After that, you pass the ref into the value.
Now, You have a ref object sharing between components under the context provider and if you want to retrieve or pass a new ref, you could use useContext hook to deal with it.
Here is the demo (codesandbox).
Here is the sample code.
import { createContext, useContext, useEffect, useRef, useState } from "react";
import "./styles.css";
const MyContext = createContext();
export const ContextStore = (props) => {
const ref = useRef();
return <MyContext.Provider value={ref}>{props.children}</MyContext.Provider>;
};
export default function App() {
return (
<>
<ContextStore>
<MyComponent />
<MyComponent2 />
</ContextStore>
</>
);
}
const MyComponent = () => {
const myContext = useContext(MyContext);
return (
<div className="App" ref={myContext}>
<h1>Hello MyComponent1</h1>
</div>
);
};
const MyComponent2 = () => {
const myContext = useContext(MyContext);
const [divRef, setDivRef] = useState();
useEffect(() => {
setDivRef(myContext);
}, [myContext]);
return (
<div className="App">
<h1>{divRef?.current && divRef.current.innerText}</h1>
</div>
);
};
You can use this approach:
VideoContext.js
import { createContext, createRef, useContext } from "react";
const VideoContext = createContext();
const videoRef = createRef();
export const VideoContextProvider = (props) => {
return (
<VideoContext.Provider value={videoRef}>
{props.children}
</VideoContext.Provider>
);
};
export const useVideoContext = () => useContext(VideoContext);
and App.js for example:
import { useState, useEffect } from "react";
import { useVideoContext, VideoContextProvider } from "./VideoContext";
const SomeComponent = () => {
const videoRef = useVideoContext();
return (
<div ref={videoRef}>
<h1>Hey</h1>
</div>
);
};
const SomeOtherComponent = () => {
const [ref, setRef] = useState();
const videoRef = useVideoContext();
useEffect(() => {
setRef(videoRef);
}, [videoRef]);
return (
<div>
<h1>{ref?.current?.innerText}</h1>
</div>
);
};
export default function App() {
return (
<>
<VideoContextProvider>
<SomeComponent />
</VideoContextProvider>
{/* ... */}
{/* Some other component in another part of the tree */}
<VideoContextProvider>
<SomeOtherComponent />
</VideoContextProvider>
</>
);
}
code sandbox
Why not? I'll say. Let's see if we can setup an example.
const fns = {}
const addDispatch = (name, fn) => { fns[name] = fn }
const dispatch = (name) => { fns[name] && fns[name]() }
const RefContext = createContext({ addDispatch, dispatch })
export default RefContext
const Child1 = () => {
const [video, dispatchVideo] = useState(...)
const { addDispatch } = useContext(RefContext)
useEffect(() => {
addDispatch('video', dispatchVideo)
}, [])
}
const Child2 = () => {
const { dispatch } = useContext(RefContext)
const onClick = () => { dispatch('video') }
...
}
The above two childs do not have to share the same ancestor.
I didn't use ref the way you wanted, but i think you can pass your ref to one of the function. This is a very basic idea. I haven't tested it yet. But seems it could work. A bit
I used this approach:
first I creacted the context and ContextProvider;
import React, { useRef } from "react";
export const ScrollContext = React.createContext();
const ScrollContextProvider = (props) => {
return (
<ScrollContext.Provider
value={{
productsRef: useRef(),
}}
>
{props.children}
</ScrollContext.Provider>
);
};
export default ScrollContextProvider;
then Added my provider in my index.js:
root.render(
<React.StrictMode>
<ScrollContextProvider>
<App />
</ScrollContextProvider>
</React.StrictMode>
);
after that I used my context where I needed it:
import React, { useContext } from "react";
import { ScrollContext } from "../../store/scroll-context";
const Products = () => {
const scrollCtx = useContext(ScrollContext);
return (
<section ref={scrollCtx.productsRef}>
// your code...
</section>
);
};
In my case I wanted to to scroll to the above component clicking a button from a different component:
import React, { useContext } from "react";
import { ScrollContext } from "../../store/scroll-context";
function Header() {
const scrollCtx = useContext(ScrollContext);
const scrollTo = () => {
setTimeout(() => {
scrollCtx.productsRef.current.scrollIntoView({ behavior: "smooth" });
}, 0);
};
return (
<header>
//your code ...
<button alt="A table with chair" onClick={scrollTo}>Order Now<button />
</header>
);
}
No. It's not possible to use Ref on context api. React ref is considered to be used on rendering element.
What you're looking for is to forward the ref, so that you can consume them wherever you want.

Dynamic color of text input in react

I want text entry to be highlighted with different colors depending on the character entered.
My hunch is that it is possible to do this by adding <span> elements with the appropriate styling inside of a contenteditable div.
Is there a better way?
Hi Please check this example. I used material-ui
import React, {useState} from 'react';
import Box from '#material-ui/core/Box';
import TextField from "#material-ui/core/TextField";
export default function BackgroundColor() {
const [text, setText] = useState('');
const [color, setColor] = useState('');
function changeHandler(event) {
setText(event.target.value);
if(event.target.value.toLowerCase() === 'a'){
setColor("primary.main");
}
else if(event.target.value.toLowerCase() === 'b'){
setColor("secondary.main");
}
else if(event.target.value.toLowerCase() === 'c'){
setColor("error.main");
}
else{
setColor("info.main");
}
}
return (
<div>
<TextField id="standard-basic" label="Standard" helperText="Type A or B or C" onChange={changeHandler} />
<Box color={color}>
{text}
</Box>
</div>
);
}
Depending on the complexity, you can also consider using Ace Editor
import React, { useState } from "react";
import AceEditor from "react-ace-builds";
import "./yamlHighlightRules";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/ace";
import "./styles.css";
export default function App() {
const [text, setText] = useState("This is the most amazing initial text.");
const handleChange = input => {
setText(input);
};
return (
<div className="App">
<AceEditor
mode="yaml"
theme="github"
name="editor"
fontSize={15}
showPrintMargin={true}
showGutter={false}
highlightActiveLine={false}
value={text}
onChange={handleChange}
setOptions={{
showLineNumbers: true,
tabSize: 2,
readOnly: false
}}
height={"600px"}
width={"100%"}
/>
</div>
);
}
And then I edited an existing set of yaml highlighting rules, it's easier not starting from scratch.
import ace from "ace-builds/src-min-noconflict/ace";
import "ace-builds/src-noconflict/mode-text";
ace.define("ace/mode/yaml_highlight_rules", [], function(require, exports) {
const oop = require("../lib/oop");
const TextHighlightRules = require("./text_highlight_rules")
.TextHighlightRules;
const YamlHighlightRules = function() {
this.$rules = {
start: [
{
token: "highlight",
regex: /amazing/
}
]
};
this.normalizeRules();
};
oop.inherits(YamlHighlightRules, TextHighlightRules);
exports.YamlHighlightRules = YamlHighlightRules;
});
The token is your css class. Just add the prefix ace_ to it. Then you define a regular expression to determine what gets that class.
.ace_highlight {
background-color: yellow;
}
Here is a codesandbox where you can see it working.
And here are the docs on defining your own modes.

How to manually trigger click event in ReactJS?

How can I manually trigger a click event in ReactJS?
When a user clicks on element1, I want to automatically trigger a click on the input tag.
<div className="div-margins logoContainer">
<div id="element1" className="content" onClick={this.uploadLogoIcon}>
<div className="logoBlank" />
</div>
<input accept="image/*" type="file" className="hide"/>
</div>
You could use the ref prop to acquire a reference to the underlying HTMLInputElement object through a callback, store the reference as a class property, then use that reference to later trigger a click from your event handlers using the HTMLElement.click method.
In your render method:
<input ref={input => this.inputElement = input} ... />
In your event handler:
this.inputElement.click();
Full example:
class MyComponent extends React.Component {
render() {
return (
<div onClick={this.handleClick}>
<input ref={input => this.inputElement = input} />
</div>
);
}
handleClick = (e) => {
this.inputElement.click();
}
}
Note the ES6 arrow function that provides the correct lexical scope for this in the callback. Also note, that the object you acquire this way is an object akin to what you would acquire using document.getElementById, i.e. the actual DOM-node.
Here is the Hooks solution:
import React, {useRef} from 'react';
const MyComponent = () => {
const myRefname= useRef(null);
const handleClick = () => {
myRefname.current.focus();
}
return (
<div onClick={handleClick}>
<input ref={myRefname}/>
</div>
);
}
Got the following to work May 2018 with ES6
React Docs as a reference: https://reactjs.org/docs/refs-and-the-dom.html
import React, { Component } from "react";
class AddImage extends Component {
constructor(props) {
super(props);
this.fileUpload = React.createRef();
this.showFileUpload = this.showFileUpload.bind(this);
}
showFileUpload() {
this.fileUpload.current.click();
}
render() {
return (
<div className="AddImage">
<input
type="file"
id="my_file"
style={{ display: "none" }}
ref={this.fileUpload}
/>
<input
type="image"
src="http://www.graphicssimplified.com/wp-content/uploads/2015/04/upload-cloud.png"
width="30px"
onClick={this.showFileUpload}
/>
</div>
);
}
}
export default AddImage;
You can use ref callback which will return the node. Call click() on that node to do a programmatic click.
Getting the div node
clickDiv(el) {
el.click()
}
Setting a ref to the div node
<div
id="element1"
className="content"
ref={this.clickDiv}
onClick={this.uploadLogoIcon}
>
Check the fiddle
https://jsfiddle.net/pranesh_ravi/5skk51ap/1/
Hope it helps!
In a functional component this principle also works, it's just a slightly different syntax and way of thinking.
const UploadsWindow = () => {
// will hold a reference for our real input file
let inputFile = '';
// function to trigger our input file click
const uploadClick = e => {
e.preventDefault();
inputFile.click();
return false;
};
return (
<>
<input
type="file"
name="fileUpload"
ref={input => {
// assigns a reference so we can trigger it later
inputFile = input;
}}
multiple
/>
<a href="#" className="btn" onClick={uploadClick}>
Add or Drag Attachments Here
</a>
</>
)
}
Riffing on Aaron Hakala's answer with useRef inspired by this answer https://stackoverflow.com/a/54316368/3893510
const myRef = useRef(null);
const clickElement = (ref) => {
ref.current.dispatchEvent(
new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
buttons: 1,
}),
);
};
And your JSX:
<button onClick={() => clickElement(myRef)}>Click<button/>
<input ref={myRef}>
Using React Hooks and the useRef hook.
import React, { useRef } from 'react';
const MyComponent = () => {
const myInput = useRef(null);
const clickElement = () => {
// To simulate a user focusing an input you should use the
// built in .focus() method.
myInput.current?.focus();
// To simulate a click on a button you can use the .click()
// method.
// myInput.current?.click();
}
return (
<div>
<button onClick={clickElement}>
Trigger click inside input
</button>
<input ref={myInput} />
</div>
);
}
this.buttonRef.current.click();
Try this and let me know if it does not work on your end:
<input type="checkbox" name='agree' ref={input => this.inputElement = input}/>
<div onClick={() => this.inputElement.click()}>Click</div>
Clicking on the div should simulate a click on the input element
let timer;
let isDoubleClick = false;
const handleClick = () => {
if(!isDoubleClick) {
isDoubleClick = true;
timer = setTimeout(() => {
isDoubleClick = false;
props.onClick();
}, 200);
} else {
clearTimeout(timer);
props.onDoubleClick();
}
}
return <div onClick={handleClick}></div>
for typescript you could use this code to avoid getting type error
import React, { useRef } from 'react';
const MyComponent = () => {
const fileRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
fileRef.current?.focus();
}
return (
<div>
<button onClick={handleClick}>
Trigger click inside input
</button>
<input ref={fileRef} />
</div>
);
}
If it doesn't work in the latest version of reactjs, try using innerRef
class MyComponent extends React.Component {
render() {
return (
<div onClick={this.handleClick}>
<input innerRef={input => this.inputElement = input} />
</div>
);
}
handleClick = (e) => {
this.inputElement.click();
}
}
imagePicker(){
this.refs.fileUploader.click();
this.setState({
imagePicker: true
})
}
<div onClick={this.imagePicker.bind(this)} >
<input type='file' style={{display: 'none'}} ref="fileUploader" onChange={this.imageOnChange} />
</div>
This work for me
How about just plain old js ?
example:
autoClick = () => {
if (something === something) {
var link = document.getElementById('dashboard-link');
link.click();
}
};
......
var clickIt = this.autoClick();
return (
<div>
<Link id="dashboard-link" to={'/dashboard'}>Dashboard</Link>
</div>
);