React Input Range updating state slowly - javascript

I'm trying to use an html element with the type="range" to make a range slider that will update a state value as I slide it back and forth. It works smoothly if I simply console.log e.target.value inside of onInputChange() without setting the state, but if I try to setState with the e.target.value, it lags so much that it's unusable. I've also tried setting the value={this.state.rangeValue} inside , with no success. Here is an example of the relevant code:
export default class App extends Component {
constructor() {
super();
this.onInputChange = this.onInputChange.bind(this);
this.state = {
rangeValue: 50
}
}
onInputChange(e) {
this.setState({ rangeValue: e.target.value});
}
render() {
var {rangeValue} = this.state;
// this logs unbearably slow and I want to be able to pass this value
// to a child component as a prop as it updates
console.log(rangeValue)
return (
<div className="map-controls">
<input type="range" onChange={this.onInputChange}></input>
<ExampleComponent rangeValue={this.state.rangeValue} />
</div>
);
}
}

I wonder if my package could help you out?
https://github.com/bluebill1049/react-smooth-range-input
import react from 'react';
import Slider from 'react-smooth-range-input';
export default () => <Slider value={1} min={1} max={30} onChange={/** you can put your callback here */} />;

#user3737841 It seems that you are updating the state of the component on onInputChange() handler. On each step value change of the input range slider, the setState is called and re-render happens. This is to be very costly to re-render on each input change.
If you avoid updating the state, you'll probably save some renders and your performance will improve.
You can also use defaultValue instead of value. Then the <input> is considered as uncontrolled and any user interactions are immediately reflected by element itself without invoking render function of your component.
Just replace value={this.state.rangeValue} with defaultValue={this.state.rangeValue}. Pass the slider value as prop to the <ExampleComponent /> component regrdless of component state.

Related

Resetting state of a component in ReactJs by changing its position in the UI tree

React will keep the state around for as long as you render the same component at the same position
in this example, I render 2 Counter components, by checking the checkbox, I control showing/hiding the first Counter component.
export default function App() {
const [showA, setShowA] = useState(true);
return (
<div>
{showA && <Counter />}
<Counter />
<label>
<input
type="checkbox"
checked={showA}
onChange={e => {
setShowA(e.target.checked)
}}
/>
Render the first counter
</label>
</div>
);
}
based on the docs, ** React keeps track of which state belongs to which component based on their place in the UI tree. You can control when to preserve state and when to reset it between re-renders.**
so when I hide/then show the first Counter, its state gets reset, the question is, by hiding and showing the first counter, we are changing the position of the second counter, yet its state doesn't get reset, any help why?
I expected that since the position of the 2nd component changes, then its state will reset as well, yet that did not happen
According to Javascript docs:
operator returns the value of the first falsy operand encountered when
evaluating from left to right, or the value of the last operand if
they are all truthy
I am no expert in Javascript / React JS, but I believe your react UI tree holds values below:
first position: false or <Counter />
second position: always <Counter />
Hence, your second <Counter />'s state will not reset.

How to render JSX component inside specific html div in react?

If I have multiple divs whose are rendered from data array using array.map() method like that:
import React,{ ReactDOM } from 'react'
import { useState,useEffect,useRef } from 'react'
import getResults from '../api/getResults'
...
function Results (props){
const [results,setResults]=useState([])
useEffect(()=>{
setResults(getResults(props.season))},
[props.season])
return (
{results.map((elem,index)=>{
return (
<div key={index} onClick={()=/*what should I do to render inside this div?*/>}>{elem}</div>
)
})}
<Details/> //I want to render this jsx inside the clicked div
)
........
}
How to get reference of specific clicked div to render Details jsx component inside this div? I tried use useRef hook but it always return the last div.
Track the clicked element in state. For example, consider this state value:
const [clickedElement, setClickedElement] = useState();
By default the value is undefined. You can update the value to some identifier when clicking one of the elements:
<div key={index} onClick={() => setClickedElement(index)}>{elem}</div>
Now each click updates state indicating which element was clicked.
Then you can use that state value to determine what to render. For example:
<div key={index} onClick={() => setClickedElement(index)}>
{elem}
{clickedElement === index ? <Details/> : null}
</div>
Basically any way you approach it, the structure is pretty much always the same:
Track information in state.
Events (e.g. a click event) update state.
UI is rendered based on state.

how to trigger onChange event on text input when the value is changed programmatically - react

render() {
return (
<input
onChange={this.handleChange}
value={this.props.transcript}
type='text
/>
)
}
in the above example, If text value is changed using keyboard inputs, it will trigger onChange event, but if it's being changed dynamically via this.props.transcript, onChange event is not triggered. How to solve this issue?
You can use componentWillReceiveProps hooks to achieve it, as your props get updated it will call componentWillReceiveProps method. Inside the method it is your playground. Please make sure this method will be called on each and every time the props changes
import React,{ Component } from 'react'
class InputBox extends Component {
componentWillReceiveProps(nextProps){
// write your logic here or call to the common method
console.log(nextProps.transcript);
}
handleChange(e){
console.log(e.target.value)
}
render(){
return(
<section>
<input
onChange={this.handleChange}
value={this.props.transcript}
type='text'
/>
</section>
);
}
}
export default InputBox;
If we are using react setState correctly it should work without issue but, Look like you have two sets of values one coming from parent "this.props.transcript" and one in input box which is handled by "this.handleChange". Alternately, check need of react hooks like "componentWillUpdate" and "componentWillReceiveProps" to apply state change on input.
Without seeing more of the code, it looks like your value for transcript in the input is wrong.
Try value={props.transcript} and if that doesn’t work value={this.state.transcript}.

Accessing a component's state when render() is called

I'm using a component library and I cannot figure this out. I'm new to react and javascript and need help.
There is a component in the library that renders a header panel with tabs.
Component
|_Component.Tab
The Tab component has 2 states that change its appearance when it is clicked. But the click handler and state changes have to be defined by me outside of Tab component. How do I do this?
Seems to me by your question that you need to use props to pass the function to change state from the Component to the Tabs. Something like this:
Component
changeState(value) {
this.setState({ appearance: value });
}
render() {
return (
<div>
<Tab
appearance={this.state.appearance}
onChangeState={this.changeState}
/>
</div>
);
}
Tab
render() {
console.log('Appearance: ', this.props.appearance); // Use it for whatever you need it
return (
<div>
<Button
onClick={(value) => this.props.onChangeState(value)} />
</div>
);
}
Not sure why do you want to handle a function and it’s state outside of the component when it has to be within the Tab component. But here is the solution what you actually have to do in your Tab component to handle your state
Bind your handler function inside a constructor like below
Eg:
this.handlerFunction = this.handlerFunction.bind(this)
Call this.handlerFunction reference in your tab onClick
Eg:
onClick={this.handlerFunction}
Set state in handlerFunction
Eg:
handlerFunction(event){
this.setState({
tabClicked: event.target.value
})
}
Else I guess The outside component should be a child component that you are talking about. If so pass your tab click state as props to your outside component (i.e., child component) and receive that state as props in your child component and do setState there.
If you are still unclear then
Post your component code here. With Just theory it’s little difficult to understand the actual problem that you are talking about.

What is the purpose of passing props to a React search bar?

I'm learning to Think in React, but don't understand why the SearchBar in the example needs to have value={this.props.filterText} and checked={this.props.inStockOnly}, the jsFiddle still works without them and it doesn't make sense for props to be passed to the SearchBar as the Search is the one handling user input and making changes to the state. The user input will be reflected in the value of the input without it being set to this.props.filterText so why is it there?
var SearchBar = React.createClass({
handleChange: function() {
this.props.onUserInput(
this.refs.filterTextInput.value,
this.refs.inStockOnlyInput.checked
);
},
render: function() {
return (
<form>
<input
type="text"
placeholder="Search..."
value={this.props.filterText}
ref="filterTextInput"
onChange={this.handleChange}
/>
<p>
<input
type="checkbox"
checked={this.props.inStockOnly}
ref="inStockOnlyInput"
onChange={this.handleChange}
/>
{' '}
Only show products in stock
</p>
</form>
);
}
});
React has concept of controlled components. A controlled component means its value is set by state (And not the other way around i.e. State being set by value of component).
Consider the following example:
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = {term : ''};
}
render() {
return (
<div>
<input value={this.state.term} onChange = {event => this.setState({term : event.target.value}) }/>
</div>
);
}
}
In above example <SearchBar /> is a Controlled Component.
Following will be sequence of events:
You type 'abc' in input field.
At this time value of input field does not change. Rather the State of component is changing because of our code in onChange Event.
As the state of component changes, the component is rendered again. And now the value of component becomes 'abc'.
This concept becomes more important when we use redux, Actions etc.
Because you will be needing the inputted value from the search bar to the upper component. For instance, if you need to filter a collection based on the given value (through search bar), then the filtering will happen on the upper component, not on the search bar. Search bar is only for the input. We put the value of the search bar from the props to make sure that the values are aligned.
The example here depicts the use of controlled input from the parent component. As you see
<input
type="text"
placeholder="Search..."
value={this.props.filterText}
ref="filterTextInput"
onChange={this.handleChange}
/>
Here the value of input box is set to {this.props.value} and in the handlechange function you are the onUserInput function which you check is again passed as a prop to the Searchbar. This calls the handleUserInput function ni the FilterableProductTable component and it sets the states filterText, inStockOnly and only these are passed as props to the Searchbar component. So although you can do without it, but controlled input is the way to go in most cases since we are accepting the value provided by the user and updating the value prop of the <input> component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. i.e. if you want to validate an input field or put restrictions on the input value its easier to do with controlled input

Categories

Resources