Manipulate React Render Properties - reactjs

I have a react component that is rendering data via the react-multi-select-component. I need to change the way the data renders. The library has a property - ItemRenderer but I'm not sure how to manipulate the properties. For example:
Current data render:
123 Item Red
124 Item Blue
204 Item Green
Desired data render:
Item Red (125)
Item Blue (124)
Item Green (204)
The actual UI code is like:
return (
<div>
<MultiSelect
options={dataListOptions}
value = {selectedListOptions}
onChange = {setSelectedOptions}
</div>
);

You can manipulate the label of each item by using ItemRenderer. See below:
export default function App() {
const options = [
{ label: "Grapes 🍇", value: "grapes" },
{ label: "Mango 🥭", value: "mango" },
{ label: "Strawberry 🍓", value: "strawberry", disabled: true }
];
const [selected, setSelected] = useState([]);
return (
<div>
<h1>Select Fruits</h1>
<pre>{JSON.stringify(selected)}</pre>
<MultiSelect
options={options}
value={selected}
onChange={setSelected}
labelledBy={"Select"}
ItemRenderer={data => data.option.label + " CHANGED"}
/>
</div>
);
}
It will render the option like this:
Grapes 🍇 CHANGED
Mango 🥭 CHANGED
Strawberry 🍓 CHANGED
In your case, since ItemRenderer props accepts a function, you just have to modify it whatever you like.

Related

How can animate between array filter methods with React?

Im currently building my personal Portfolio and I have an array of objects containing multiple projects, each one of the project object contain a property called category, which can have a value of 'Visual' or 'Complexity'.
My plan is to add two buttons, one for each category, but I would like to animate between the category changes, a simple fade out and fade in would be nice, any idea how can I do this ?
I tried using React Transition Group for this, but didn't manage to figure it out.
The first Component is the ProjectUl, this component will receive a filter prop, which is basically a string indicating which category should the filter method use.
const projects = [
{
name: "Limitless",
category: "visual",
dash: "- Landing Page",
img: imgList.limitless,
gif: imgList.limitlessGif,
},
{
name: "Spacejet",
category: "complexity visual",
dash: "- Landing Page / API Project; ",
img: imgList.spacejet,
},
];
export const ProjectsUl: FC<IProps> = ({ filter }) => {
const [filtered, setFiltered] = useState<IProject[]>([])
useEffect(() => {
const filteredProjects = projects.filter((i) => i.category.includes(filter));
setFiltered(filteredProjects);
}, [filter]);
return (
<ProjectsUlStyle>
{filtered.map((i) => (
<ProjectsLi filtered={i} />
))}
</ProjectsUlStyle>
);
};
Then, inside the ProjectsUl there will be the ProjectsLi, which are the list of projects, here is the code for the ProjectsLi
export const ProjectsLi: FC<any> = ({ filtered }) => {
return (
<LiStyle>
<img src={filtered.img} />
<div>
<span className="dash">{filtered.dash}</span>
<header>
<h1>{filtered.name}</h1>
<FAicons.FaGithub />
<FAicons.FaCode />
</header>
</div>
</LiStyle>
);
};

How to make MUI's Autocomplete display the label from the matching value in props.options?

I have a multilingual website where there are certain Autocompletes whose options array need to have its items labels translated, which is done very easily.
However, it would be harder to update the current chosen value, stored elsewhere. Since Autocomplete uses the label from the value prop instead of using the item of same ID within options, it ends up like this:
const vehicles = [
{ id: 1, label: "Car" },
{ id: 2, label: "Bus" }
];
const currentVehicleValue = {
id: 2,
label: "Ônibus"
};
export default function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={vehicles}
value={currentVehicleValue}
renderInput={(params) => <TextField {...params} label="Vehicle" />}
/>
);
}
Is there a way to just tell Autocomplete to use the label inside the options prop instead of the one within the value
demo
EDIT: I mean to have the label within options being shown while I don't type anything. As in, the language changed, the options were translated, but the currentValue was not, so it would be nice to have the Autocomplete use the label from the matching item within options as long as I don't type anything.
Edit after clarification
You can change how the <TextField/> is rendered by tweaking the props it receives.
In the example below, I find the currentVehicle by its id and change the inputProps.value to be the vehicle label.
Also, to ensure MUI finds the currentValue correctly within the options, you will need to use the isOptionEqualToValue to compare the options ids instead of strict equality
const vehicles = [
{ id: 1, label: "Car" },
{ id: 2, label: "Bus" }
];
const currentVehicleValue = {
id: 2,
label: "Ônibus"
};
function compareValueToOption(option, value) {
return option.id === value.id;
}
function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={vehicles}
value={currentVehicleValue}
renderInput={ComboBoxInput}
isOptionEqualToValue={compareValueToOption}
/>
);
}
function ComboBoxInput(props) {
const currentVehicle = vehicles.find(
(vehicle) => vehicle.id === currentVehicleValue.id
);
props.inputProps.value = currentVehicle.label;
return <TextField {...props} label="Vehicle" />;
}
Here's a working demo

Access selected value from react's Select Component

Hello dear community,
I want to create a very basic website for my school assignment.
I have a dropdown menu with a Select Component as its implementation. I need to access the selected value, which is a currency in my case, in order to update the information displayed on the page once a currency has been selected.
I am kind of frustrated since I wasn't able to find a helpfull solution to my relatively basic problem (I think it's basic :D)
My component class here:
import { Component } from "react";
import Select from 'react-select';
interface DropdownMenuProps {
values: [{}]
defaultValue: string
}
interface DropdownMenuState { }
/**
* Represents a Dropdown Menu
*/
export default class DropdownMenu extends Component<DropdownMenuProps, DropdownMenuState> {
render() {
return (
<div style={{ width: '120px' }}>
<Select id="dropdown-menu"
placeholder={this.props.defaultValue}
options={this.props.values}
// getOptionValue={(option) => option.value}
// getOptionLabel={(option) => option.label}
/>
</div>
)
}
}
This is how I create a dropdown menu compent:
<DropdownMenu defaultValue="Currency" values={[{ label: "EUR", value: "EUR" }, { label: "GBP", value: "GBP" }, { label: "USD", value: "USD" }]} ></DropdownMenu>
I'm glad for any tips :)
You have to use the onChange prop of react-select:
<select
id="dropdown-menu"
onChange={handleSelectChange}
>
and in this function you could handle the changes:
const handleSelectChange = (selectedVal) => console.log(selectedVal)
I recommend you using directly onChange and save it into a state:
1st:
Create state with the name you want:
const [selectValue, setSelectValue] = useState({});
2nd: Create options:
const options = [
{ label: "Tomate", value: 1 },
{ label: "Queso", value: 2 }
];
3rd: add method onChange in select and pass options:
const onChange = (ev) => {
setSelectValue(ev);
//console.log(ev);
console.log(selectValue);
};
<Select
id="dropdown-menu"
placeholder={"e"}
options={options}
onChange={onChange}
/>
I have created demo here:
https://codesandbox.io/s/ancient-pond-96h53?file=/src/App.js

How can I set null as default value in Slider from Material UI

I'm checking the documentation and looks like Slider requires the values to be an integer and also fallback to the first or the last item in case I pass a number that is not in the list of values for the Slider.
I'm creating a component that asks the user to select one of these:
Never | Rarely | Sometimes | Frequently | Almost always | Always
But it doesn't make sense to me to have an initial one selected. The options should show up initially as none of them selected. Is this something that Slider was not created to do? Looks so simple not having a value as default. Am I missing something?
Material UI Slider docs: https://material-ui.com/api/slider/
Currently, it is not possible to have MuiSlider without value. It will pick value from defaultValue or value.
For your use case, in case you need to use Slider component, you need to introduce one more extra value (only for UI sake)
import { Typography, Slider } from "#material-ui/core";
const marks = [
{ label: "None", value: 0 },
{
label: "Never",
value: 1
},
{
label: "Rarely Sometimes",
value: 2
},
{
label: " Frequently",
value: 3
},
{
label: "Almost always",
value: 4
},
{
label: "Always",
value: 5
}
];
export default function DiscreteSlider() {
const [sliderValue, setSliderValue] = useState(marks[0].value);
const onSliderValueChange = (e, val) => {
setSliderValue(val);
};
return (
<div>
<Typography id="discrete-slider" gutterBottom>
Slider
</Typography>
<Slider
aria-labelledby="discrete-slider"
valueLabelDisplay="off"
value={sliderValue}
onChangeCommitted={onSliderValueChange}
marks={marks}
min={0}
max={5}
/>
</div>
);
}
Else you can also check for Rating component available in lab version and map its rating with your selection values.
import Rating from "#material-ui/lab/Rating";
import Typography from "#material-ui/core/Typography";
export default function SimpleRating() {
const [value, setValue] = React.useState(0);
return (
<div>
<Rating
name="simple-controlled"
value={value}
onChange={(event, newValue) => {
setValue(newValue);
}}
/>
</div>
);
}

react-select property name for value

I have this code:
import React from "react";
import ReactDOM from "react-dom";
import Select from "react-select";
const optionsExample = [
{
code: "CLP",
country: "CLP",
minimumAmount: 10000
},
{
code: "USD",
country: "US",
minimumAmount: 25000
}
];
const handleChange = (newValue, actionMeta) => {
console.log("change newValue", newValue); // object changes but it's not selected the right one
};
const CustomControl = () => (
<Select
defaultValue={optionsExample[0]}
formatOptionLabel={({ code }) => code}
options={optionsExample}
onChange={handleChange}
/>
);
ReactDOM.render(<CustomControl />, document.getElementById("root"));
It doesn't work ok because react-select expect that the value of each object on the data array be named value. How can I pass data like in the example? I need that data has those properties, I can't change country to value.
Actually, I used the props formatOptionLabel to change the default label field from the object to code but I don't know how to do the same but for the value.
Demo with my code, with the problem:
https://codesandbox.io/s/react-select-formatoptionlabel-forked-deuw1?file=/index.js:0-756
This is working because each object has it's value field and that's what is expected by react-select
https://codesandbox.io/s/react-select-formatoptionlabel-forked-d9bdj
If you can't move the mountain, then walk around it.
use inline .map to convert your array of objects
const CustomControl = () => (
<Select
defaultValue={optionsExample[0]}
formatOptionLabel={({ code }) => code}
options={optionsExample.map(x => ({ value: x.country, label: x.code })}
onChange={handleChange}
/>
);
or better still use useMemo to create a new array, if your array changes
const selectOptions = useMemo(() => optionsExample.map(x => ({ value: x.country, label: x.code }),[optionsExample])
<Select
defaultValue={selectOptions[0]}
formatOptionLabel={({ code }) => code}
options={selectOptions}
onChange={handleChange}
/>

Resources