How to output current values from the rc-slider react component? - javascript

I installed the rc-slider React Component on my React app, but I need to output the current values from the slider, how do I do that? This is the current code:
import React from 'react';
import 'rc-slider/assets/index.css';
import 'rc-tooltip/assets/bootstrap.css';
import Slider from 'rc-slider';
const createSliderWithTooltip = Slider.createSliderWithTooltip;
const Range = createSliderWithTooltip(Slider.Range);
export class RangeSlider extends React.Component {
render() {
return (
<div>
<Range min={0} max={10000} defaultValue={[800, 3000]} tipFormatter={value => `${value}€`} />
</div>
)
}
}
Also, how do I change the font-family from the tooltip where values are displayed when grabbing slider's handles?

You could store the slider values in state and use the onChange prop to update the slider values when they change.
The function given to tipFormatter can also return JSX as well as a string, so you can add a custom className and change font-family for that class.
Example
export class RangeSlider extends React.Component {
state = { sliderValues: [800, 3000] };
handleChange = sliderValues => {
this.setState({ sliderValues });
};
render() {
const { sliderValues } = this.state;
return (
<div>
{sliderValues[0]} - {sliderValues[1]}
<Range
min={0}
max={10000}
onChange={this.handleChange}
defaultValue={sliderValues}
tipFormatter={value => <span className="tooltip">{value}€</span>}
/>
</div>
);
}
}

For some reason, that last part of your code was not working for me as I was trying to get the range tooltip to animate correctly and display the correct data. I had to install an older version of rc-slider (8.7.1) in order to fix the tooltip animation that is currently broken at the time of this post. The code fix that got it all working correctly with the older version was:
...
tipFormatter={value => ${value}}
tipProps={{visible: true}}
...

Related

Giphy React Grid component is not working

I am trying to replicate the search and masonry grid from the official documentation using their Codesandbox example.
However, when I am trying to use it, the code is not returning any gifs back.
I have verified that the JS fetch is indeed returning back gifs, it seems that the grid is not calling the fetchGifs function.
I am hitting the same issue with Carousel component as well.
Can anyone help me with this issue?
Codesandbox link for my implementation - https://codesandbox.io/s/cocky-waterfall-ny9rzk
Component i was trying to use - Search and Grid from https://github.com/Giphy/giphy-js/tree/master/packages/react-components
import { GiphyFetch } from "#giphy/js-fetch-api";
import { Grid } from "#giphy/react-components";
import useDebounce from "react-use/lib/useDebounce";
import React, { useState } from "react";
export default function App() {
const giphyFetch = new GiphyFetch("PZpYG85wQpugMlEx02GGqeKfKZ8eMdFZ");
const [debouncedInput, setDebouncedInput] = useState<string>("");
const [term, setTerm] = useState<string>("");
useDebounce(() => setTerm(debouncedInput), 500, [debouncedInput]);
const NoResults = <div className="no-results">No Results for {term}</div>;
const fetchGifs = (offset: number) => {
return giphyFetch.search(term, { offset, limit: 10 });
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<input
placeholder="type to search"
onChange={({ target: { value } }) => setDebouncedInput(value)}
value={debouncedInput}
/>
<Grid
key={term}
columns={3}
gutter={6}
noResultsMessage={NoResults}
width={400}
fetchGifs={fetchGifs}
/>
</div>
);
}
Try removing strict mode here:
https://codesandbox.io/s/cocky-waterfall-ny9rzk?file=/src/index.tsx
I guess the Grid is incompatible with React 18, possibly due to the useEffect change it brings.
Alternatively you could use React 17.x
Updated looks like they've introduced a fix
https://github.com/Giphy/giphy-js/commit/dade2aa10442c9ca8e6741125071dc1053e89181

How to remove component that is rendered from a list? React Native

I've been following this tutorial for ReactJS and have been trying now to convert the simplistic Todo App (just checks off and on items) to React Native. I've been using expo to try it live on my phone and everything.
It all went good, but now I'm trying to add something. Whenever I click the checkbox I want to remove the component related to that item.
My idea was:
Since I'm rendering the TodoItem components from an array of todos,
and whenever I click a checkbox it updates the array as a whole
(looking for a certain id and updating it's completed variable). I can
run through the array and whenever the id is different I return the
todo. This way I returned every todo but the one with matching id to
be rendered.
import React, { Component } from 'react';
import { Alert,Image,StyleSheet, Text,Button, View } from 'react-native';
import TodoItem from './TodoItem'
import todosData from "./todosData"
export default class App extends React.Component {
constructor() {
super()
this.state = {
todos: todosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState(prevState => {
const updatedTodos = this.state.todos.map( todo => {
if(todo.id !== id) {
return todo
}
})
return {
todos:updatedTodos
}
})
}
render() {
const todoItems = this.state.todos.map( item =>
<TodoItem
key={item.id}
item={item}
handleChange = {this.handleChange}
/>
)
return (
<View style={styles.container}>
{todoItems}
</View>
);
}
}
This gives an error: ' TypeError:undefined is not an object (evaluating 'item.id')', giving at App.js:42:18
I'll also add the code referring to the TodoItem:
import React, { Component } from 'react';
import { Alert,Image,StyleSheet, Text,Button, View } from 'react-native';
import { CheckBox } from 'react-native-elements'
function TodoItem(props) {
return (
<View>
<CheckBox
checked={props.item.completed}
onPress={() => props.handleChange(props.item.id)}
/>
<Text>{props.item.text}</Text>
</View>
);
}
export default TodoItem
I don't understand why this won't work. It feels like I'm deleting the component while still using it (for it to give a undefined), but I don't see where. Since I'm simple updating a list of todos.
How can I do the thing I want?
PS: I seem unable to properly format the first segment of code. I apologize for that!
Try this:
handleChange(id) {
const { todos } = this.state
// filter out the deleted one
const filtered = todos.filter(x => x.id !== id)
this.setState({ todos: filtered })
}
We don't want to alter the state directly, but since .filter() creates a new array, without touching the given array, it is fine to use it. if it was another operation, you'd do something like this:
// create a copy
const newSomethings = [...this.state.somethings]
// do whatever with newSomethings
this.setState({ somethings: newSomethings })

How do I re render the entire React Pivot Table UI component when I change the selection in select tag?

I am new to react js and I am trying to create a pivot table using React Pivot table. I want to be able to select a data set using a select drop down menu and update the state and re render the full table whenever there is a change in the drop down selection just like the jquery example shown here https://pivottable.js.org/examples/rcsvs.html
It works before I make any selections or changes to the Pivot Table. I am able to toggle between the 2 datasets and the state changes in the Pivot table. But when I select a pivot dimension and use the pivot table, after that point, changing the select menu does not help me change the pivot table's state. Please help.
Here's my code.
import React from 'react';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import 'react-pivottable/pivottable.css';
import TableRenderers from 'react-pivottable/TableRenderers';
import Plot from 'react-plotly.js';
import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
// create Plotly renderers via dependency injection
const PlotlyRenderers = createPlotlyRenderers(Plot);
const data1 = [{'Country':'USA','Sales':45000},
{'Country':'USA','Sales':50000},{'Country':'CA','Sales':15000}]
const data2 = [{'Product':'Sofa','Sales':5000},{'Product':'Dinner
Table','Sales':50000},{'Product':'Chair','Sales':15000}]
const dataDic = {'Region':data1,'Products':data2}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {selectedOption: 'Region'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({selectedOption: event.target.value});
}
handleSubmit(event) {
alert('You have selected ' + this.state.selectedOption);
event.preventDefault();
}
render() {
return <div>
<select defaultValue="Region" onChange={(e)=>
this.handleChange(e)}>
<option value="Region">Region</option>
<option value="Products">Products</option>
</select>
<br/>
<br/>
<PivotTableUI
data={dataDic[this.state.selectedOption]}
onChange={s => this.setState(s)}
renderers={Object.assign({},TableRenderers)}//,PlotlyRenderers)}
{...this.state}
/>
</div>;
}
}
export default App;
I found that if I delete the data property from s
<PivotTableUI
data = {[{}]}
onChange={ s =>{
delete s.data
this.setState(s)
}}
{...this.state}
/>
This won't overwrite the data in the parent class and will be automatically rendered with updated data
Working code sandbox
There were two problems;
s => this.setState(s) in your PivotTable's onChange property.
This overrides root state with all the props of your PivotTable.
When your page initiated, container's (Grid) state only contains selectedOption:"Region" but after interacting with the PivotTable, container has receives all the props of the PivotTable. Screenshot:
{...this.state} prop in PivotTableUI component, passes all keys as props in container's state including data.(As seen in the screenshot above). And this overrides data property, data={dataDic[this.state.selectedOption]} After this, changes to selectedOption state does not re-render PivotTableUI
Solution
Change s => this.setState(s) with this.setState({ pivotTableUIConfig: s });
Define a pivotTableUIConfig variable which does not include data property. (Used ES7 Object Rest Operator to Omit data property)
// Picking all the properties except "data"
const { data, ...pivotTableUIConfig } = this.state.pivotTableUIConfig;
Change {...this.state} with {...pivotTableUIConfig}
Encountered the same problem and found a simple fix. The problem is that data prop always gets overwritten by {...state}. Hence we can assign data to state before passing it to PivotTableUI. And the data prop is no longer needed.
const state = {...this.state};
state['data'] = dataDic[this.state.selectedOption];
return (
<PivotTableUI
onChange={s => this.setState(s)}
{...state}
/>
)
you should add
renderers={{ ...TableRenderers, ...PlotlyRenderers }}
{...state}
to your PivotTableUI, see the full example:
import TableRenderers from 'react-pivottable/TableRenderers';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import Plot from 'react-plotly.js';
import createPlotlyRenderers from 'react-pivottable/PlotlyRenderers';
import 'react-pivottable/pivottable.css';
const PlotlyRenderers = createPlotlyRenderers(Plot);
function DataExploration() {
const { dashboardData: { data } } = useSelector((state) => state.dashboardData)
const ExpComp = (props) => {
const [state, setState] = useState(props);
return (
<div className="row">
<div className="col-md-12">
{
<PivotTableUI
style={
{
width: "100%",
height: "100%"
}
}
onChange={(s) => setState(s)}
renderers={{ ...TableRenderers, ...PlotlyRenderers }}
{...state}
/>
}
</div>
</div>
)
}
return (
<ExpComp data={data} />
)
}
From more details check the doc: https://github.com/plotly/react-pivottable

States do not change when using styled components in React

I am trying to implement a search bar while using the styled-components library for styling. My issue is that the queried value never changes if I used styled-components. This is my code
import styled from 'styled-components'
import React, from 'react'
const SearchBar = styled.input`
margin-top: 35px;
float: right;
`
class Header extends React.Component {
state = {
query: '',
}
handleNewQuery = () => {
this.setState({
query: this.search.value,
})
console.log(this.search.value);
}
render () {
return (
<SearchBar
placeholder='Search for...'
ref={input => this.search = input}
onChange={this.handleNewQuery}
/>
)
}
}
Which only works if I swap SearchBar with input, otherwise the log prints undefined
The base issue is the the ref that is being created is returning a StyledComponent, not an HTML input element. It simply does not have a value property. The reason it starts working when you removing the styled aspect and simply render an <input />, is then the ref is an actual HTML input element with a value property. Try logging the ref in the change event to see this with first the styled component then a standard input. Either way I'd try approaching it as a Controlled Component using value property and event.target.value instead of attempting to extract the value from a ref.
import React, { Component } from 'react';
import styled from 'styled-components';
import './style.css';
const SearchBar = styled.input`
margin-top: 35px;
float: right;
`;
class Header extends Component {
constructor() {
super();
this.state = {
query: ''
};
}
handleNewQuery = (e) => {
this.setState({
query: e.target.value
})
}
render() {
return (
<div>
<SearchBar
placeholder='Search for...'
onChange={this.handleNewQuery}
value={this.state.query}
/>
</div>
);
}
}
If you absolutely must use a ref with this styled component. You can used the property innerRef which is specific to styled components to access the underlying HTML input element. This would technically give you access the value property. Once again though, the best approach would simply be using a controlled component as described above. The below example is using the newer approach to creating refs, but it would depend on your version of React being used.
<SearchBar
placeholder='Search for...'
onChange={this.handleNewQuery}
value={this.state.query}
innerRef={this.search}
/>
Here is a StackBlitz showing the functionality in action including the innerRef.
Hopefully that helps!
SearchBar should take a value prop instead of using a ref to get the value. Something like this:
<SearchBar value={this.state.search} ... />

React contentEditable and cursor position

I have simple component
class ContentEditable extends React.Component {
constructor(props) {
super(props);
this.handleInput = this.handleInput.bind(this);
}
handleInput(event) {
let html = event.target.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({ target: { value: html, name: this.props.name } });
this.lastHtml = html;
}
}
render() {
return (
<span
contentEditable="true"
onInput={this.handleInput}
className={"auto " + this.props.className}
dangerouslySetInnerHTML={{ __html: this.props.value }}
/>
);
}
}
export default ContentEditable;
<ContentEditable
value={this.state.name}
onChange={e => {
this.setState({ name: e.target.value });
}}
/>;
The component works but the cursor position never changes, it is always on first position instead after the rendered text.
I tested examples form this forum but it doesn't work for me.
I use React 15.6.1 and test it on chrome (Os X).
Any hint how I can solve this problem?
The solution with useRef will be something look like below.
Here the useRef will keep the default value / initial value apart from the component rendering cycles, so it will retain the original value without being affected by other kinds of operations we do in the react component.
This component does two things
This will emit the user input to the parent component with an onChange method
Takes a default value from parent component as prop named value and renders the value in the custom input box (that was created using contentEditable)
I have added a code sandbox, link here, use this to see how this works!
The code sandbox example contains two components
one is ContentEditableWithRef which solves the problem with useRef , which is an uncontrolled component and
the other component is ContentEditable which uses useState to solve the same problem.
I also had same problem. Just fixed it with ref. Just assign textContent of event.target to ref.
const textareaEl = useRef<HTMLDivElement>(null);
const handleChange = (e: React.ChangeEvent<HTMLDivElement>) => {
textareaEl.current.textContent = e.target.textContent;
onChange(e); // If you have change event for form/state
};
/** If you're passing value from state,
you can mutate it each change for not losing cursor position.
*/
useEffect(() => {
if (value) {
textareaEl.current.textContent = value;
}
}, [value]);
return (
<div
id="textarea-element"
ref={textareaEl}
contentEditable={true}
suppressContentEditableWarning={true}
onChange={handleChange}
/>
)

Categories