add onChange to input in string in react - javascript

I'm using react for my project and I have the string below.
const text= "<p><strong>Late 19th Century</strong></p><ul><li>in Yellowstone Park, every type of <input type="text" /> was prohibitedas</li></ul>"
and I use :
<div dangerouslySetInnerHTML={{ __html: text }}></div>
how to handle onChange input when I use dangerouslySetInnerHTML on string in react.

At this point you're working with native HTML, it is no longer React and you cannot treat it as such. You'll either have to go down the rabbit trail of manually attaching event listeners to the set HTML or just use React as it's intended.
NOTE: I'm assuming you have a good reason to do this. Otherwise, I do not recommend this for normal use-cases in React.
That said, here is a way you could still use the string of HTML with React's state.
For simplicity I added an id attribute to the input in your string. Also note that, because of the difference in when the native DOM change event fires vs the React change event, you have to click out of the input to see the new value.
const {useState, useEffect} = React;
const text= '<p><strong>Late 19th Century</strong></p><ul><li>in Yellowstone Park, every type of <input id="myText" type="text" /> was prohibitedas</li></ul>'
const Example = () => {
const [value, setValue] = useState('');
useEffect(() => {
const el = document.getElementById('myText');
el.addEventListener('change', (e) => setValue(e.target.value));
}, []);
console.log('value', value);
return <div dangerouslySetInnerHTML={{ __html: text }}></div>;
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Related

setFunction of useState won't change OnClick

I have this useState element, but the function doesn't get called onClick.
I have tried many solutions and debugging and it seems like the Click event doesn't get called, no matter what.
const [modalHotel, setModalHotel] = useState(false)
{modalHotel && <ModalHotel CloseModal = {setModalHotel} />}
<img src="./assets/square.svg" alt="expand" onClick={() => setModalHotel(!modalHotel)}/>
Sometimes elements won't register onClick events in React unless you specify a tabIndex. Try this:
const checkClick = () => {
console.log("It worked!!");
setModalHotel(!modalHotel);
}
<img tabIndex={0} src="./assets/square.svg" alt="expand" onClick={checkClick} />
this will help you to debug whether the click event is actually being fired.
Side Note:
From an accessibility perspective, it's almost always preferrable to use either button or a elements to handle clicks like this. They have tabIndexes by default, and better a11y support in general.
Found the problem!
I had this z-index: -1; in my css, removed it and it worked.
You haven't really provided enough information to completely diagnose your issue. But in the meantime, here is a working snippet with an element that is clickable (a button) to toggle state using a useState hook. You can compare what is different between your non-working code and this working example.
const { useState } = React;
const Thing = (props) => {
const [modalHotel, setModalHotel] = useState(false);
return (
<div>
<h1>{modalHotel.toString()}</h1>
<button onClick={() => setModalHotel(!modalHotel)}>Toggle</button>
</div>
);
}
ReactDOM.render(
<Thing />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How do I update the default useSate value from a html input?

This Is a simple question. I have a React useState hook,
const [seconds, setSeconds] = useState(0);
how would I be able to update the useState default of 0 to any number I enter, from some kind of a text box or Input in HTML?
Thanks in advance.
You need to add a change event in the input then add the function to handle the input change. like this example.
export default function App() {
const [seconds, setSecond]= useState(0);
const handleSeondChange = (event)=>{
setSecond(event.currentTarget.value);
}
return (
<div className="App">
<input name ="seconds" value={seconds} onChange={handleSecondChange}/>
</div>
);
}
Within an input tag include an onChange handler. For example, <input onChange={(event) => setSeconds(event.target.value)} value={seconds}/>. You're dealing with a controlled input here, so make sure you include the value tag within the input like I included above.

React Error: Too many re-renders. while using arrow function

I am making a calculator in react in which i made buttons for numbers and when button "7" is pressed then in the input field 7 is added.
My approach:
I am using useState to do this.
I made an arrow function funinpval which takes takes number as string in argument then i am using this function with different buttons onclick handler by passing respective numbers as arguments. But I am getting error
import React from 'react'
import { useState } from 'react';
export const Calculator = () => {
const [inpval, setInpval] = useState("")
const funinpval = (num) => {
setInpval(inpval + num)
}
return(
<>
<input type="text" value={inpval}>
<button onClick={funinpval("7")}>7</button>
<button onClick={funinpval("8")}>8</button>
</>
)
Can anyone please help
<button onClick={funinpval("7")}>7</button>
<button onClick={funinpval("8")}>8</button>
You are not waiting the user to click the buttons to execute the functions, they are instead executed every render phase, directly. Which mean that the component render -> state update -> new re-render -> new state update -> ...
To fix it:
<button onClick={() => funinpval("7")}>7</button>
<button onClick={() => funinpval("8")}>8</button>
There is a syntax error in how you are providing the event handlers.
You have to provide event handlers sonething like:
<button onClick={() => funinpval("7")}>7</button>
<button onClick={() => funinpval("8")}>8</button>
Simply writing onClick={funinpval("7")} will immediately call the function while rendering which sets the state. When state got updated then the component re-renders. Then again while re-rendering, this function got called and so on.
onClick={funinpval("7")}
will return the result of calling that function to the listener rather than a reference to the function that the listener can call. So you're setting state immediately with those two buttons which is causing the render which is calling the function again which is setting the state again... infinity!
In this example I pick up the textContent of the button and use that to set the new input state, and then you can simply just pass the reference to the function to the handler and let the function deal with how state is set.
const { useState, useEffect } = React;
function Calulator() {
const [inpval, setInpval] = useState(0);
function funinpval(e) {
// Grab the `textContent` of the button and
// relabel it to `num` making sure to coerce the
// text to a number first
const { textContent: num } = e.target;
setInpval(inpval + Number(num));
}
return(
<div>
<input type="text" value={inpval} />
<button onClick={funinpval}>7</button>
<button onClick={funinpval}>8</button>
</div>
)
};
// Render it
ReactDOM.render(
<Calulator />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

What's the material-ui <select> equivalent of <input type="color"><datalist>?

I'm new to javascript, react, and Material-UI so my question (and code sample) may be naive.
I have the following code in a Material-UI TableCell (not a form):
<input type="color" name="backgroundColor" list="categoryColours" id="categoryColour"/>
<datalist id="categoryColours">
{colourOptions.map((val) =>`<option value=${val.value}>${val.value}</option>`)}
</datalist>
I like the colour picker it produces (it renders the 25 colour swabs in a nice grid), but I would like to replace this with the appropriate Material-UI component. Is there such a thing?
I'm going to use material-ui-color. It's not part of the Material-UI library, but it is a compatible module that can do both colour picker and colour swabs.
The current URL is https://www.npmjs.com/package/material-ui-color.
The provided example is:
<div>
<ColorPicker defaultValue="black" palette={paletteObj} />
</div>
There is also a package for Material UI v5 (or MUI) called Mui color input and it's working with React 17 and 18 !
Simply way to use. Color validation available too.
Check the doc here : https://github.com/viclafouch/mui-color-input
import React from 'react'
import { MuiColorInput } from 'mui-color-input'
const MyComponent = () => {
const [value, setValue] = React.useState('#ffffff')
const handleChange = (newValue) => {
setValue(newValue)
}
return <MuiColorInput value={value} onChange={handleChange} />
}

React add html attribute to external component

I am using a component that I cannot change directly, but I would like to extend.
import { Button } from '#external-library'
// Currently how the button component is being used
<Button click={() => doSomething()} />
// I would like to add a tabIndex to the button
<Button click={() => doSomething()} tabIndex={0} />
I cannot add an attribute because the component is not expecting a tabIndex. I cannot directly modify the Button component.
How can I extend the <Button /> component so I can add attributes like tabIndex, etc?
I was hoping something like the following would work:
export default class ExtendedButton extends Button { }
// except I'm dealing with functional components
You can't edit custom component implementation without changing its internals.
// You can't add tabIndex to internal button without changing its implementation
const Button = () => <button>Click</button>;
In such cases, you implement a wrapper with desired props:
const Component = () => {
return (
<div tabIndex={0}>
<Button />
</div>
);
};
If the component forwarding ref (also depends to which element it forwarded in the implementation), you can use its attributes:
// Assumption that Button component forwards ref
const Button = React.forwardRef((props,ref) => <button ref={ref}>Click</button>);
<Button ref={myRef}/>
// Usage
myRef.current.tabIndex = 0;
You can access the inner DOM button element using React refs(read here)
most likely the external-lib you use provide a ref prop for the Button component which you use to pass your own create ref
const buttonRef = useRef(null);
<Button ref={buttonRef}/>
Then you can use buttonRef.current to add tabIndex when your data is ready to be populated in like
useEffect( () => {
if(buttonRef && buttonRef.current){
buttonRef.current.tabIndex = 2;
}
}, [props.someProperty] );

Categories

Resources