How to take out props data from a component in react-js? - javascript

I am working on a react.js app with react-select using which I have made one dropdown menu and on click of an item in menu I want to pass that item to a function which is later connected to redux store.How can I access data from a component that is used in react-select?
Here's my code that will give you more reference.
const Option = (props) => {
return (
<components.Option {...props} >
<div>{props.data.api}</div>
<div style={{ fontSize: 12 }}>{props.data.group}</div>
</components.Option>
);
};
The above code is my Option component which is used below to render a Select Menu.
return (
<StyledForm id="form_container">
<Grid>
<Grid.Row>
<Grid.Column width={3}>
<input
label="Client Name"
value={this.props.clientName}
onChange={this.setClientName}
/>
<Select options={this.props.clientGrantList} components={{ Option }} onChange={()=>this.addApiGrants(//how to pass data)} />
</Grid.Column>
This is my UI component where select menu is showing.
In the below Line in addApiGrants function I want to pass in select option data.How can I do it?
<Select options={this.props.clientGrantList} components={{ Option }} onChange={()=>this.addApiGrants(//how to pass data)} />
Thanks

The onChange handler function receives selected object as an argument. So, the code to handle this would be :
const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
export default function App() {
return (
<div className="App">
<Select options={options} onChange={item => addApiGrants(item)} />
</div>
);
}
This is how the selected item from onChange handler looks like
{value: "strawberry", label: "Strawberry"}

Related

How to bind the selected option from the drop down to a reactjs state property in functional component and show it to side of the dropdown

I am new to react js. I have written a code for selecting the option for the perticular question. I just want to display the selected option next to the drop down. But when I selected the option it is displaying the same value for all the questions. could anyone please help me in resolving this.
import "./styles.css";
import { useState } from "react";
export default function App() {
const [select, setSelect] = useState("");
const optionchanged = (e) => {
setSelect(e.target.value);
};
const questions = [
{
id: 1,
qst: "which country you are from",
options: ["select", "USA", "UK", "Australia", "India"]
},
{
id: 2,
qst: "What is your country code",
options: ["select", "+1", "+44", "+61", "+91"]
}
];
return (
<div className="App" style={{ "text-align": "left" }}>
{questions.map((quest) => (
<div>
{/* displaying the question */}
<p>
{" "}
{quest.id}. {quest.qst}
</p>
{/* showing the options */}
<select onChange={optionchanged}>
{quest.options.map((option) => (
<>
<option> {option}</option>
</>
))}
</select>
{/* selected option showing next to the dropdown */}
<span style={{ color: "blue" }}>{select} </span>
</div>
))}
</div>
);
}
here is the output I got , here the second question also giving the same option without selecting it.
[1]: https://i.stack.imgur.com/tFyu8.png
You need store the value related to every select separately, to achieve your goal, you can define different states, or you can store values in an object instead of string, like this:
function App() {
const [select, setSelect] = React.useState({});
const optionchanged = (e, id) => {
setSelect( select => ({ ...select, [id]: e.target.value }) );
};
const questions = [
{
id: 1,
qst: "which country you are from",
options: ["select", "USA", "UK", "Australia", "India"]
},
{
id: 2,
qst: "What is your country code",
options: ["select", "+1", "+44", "+61", "+91"]
}
];
return (
<div className="App" style={{ "text-align": "left" }}>
{questions.map((quest) => (
<div>
{/* displaying the question */}
<p>
{" "}
{quest.id}. {quest.qst}
</p>
{/* showing the options */}
<select onChange={e => optionchanged(e, quest.id)}>
{quest.options.map((option) => (
<option> {option}</option>
))}
</select>
{/* selected option showing next to the dropdown */}
<span style={{ color: "blue" }}>{select[quest.id]} </span>
</div>
))}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You need to create different state variables for both fields. As of now both the field values are stored to the same state.

React-select multiple selects on one page

I am a bit confused, here is an example with a couple of select inputs that have the same state, please check here: https://stackblitz.com/edit/get-selected-by-value-multi-select-react-agamk4?file=src/App.js so please:
How can I make it so when I select an option the value does not apply to the rest of the select inputs?
How would you put the values in the store for each of the selects?
Do I need multiple stores?
For more clarity, here is a screenshot: https://www.awesomescreenshot.com/image/19798040?key=bb839c650c93b436066e03d33d5515b0 I hope this makes sense? What would be the best approach? Thank you.
I have shared the code in case of only a single state. You can use this method if you want only a single state but having multiple states for different select inputs also won't be bad as you have only 3 inputs. Having single state method would be useful if number of select inputs would have more.
import React, { useState } from 'react';
import Select from 'react-select';
function App() {
const data = [
{
value: 1,
label: 'cerulean',
},
{
value: 2,
label: 'fuchsia rose',
},
{
value: 3,
label: 'true red',
},
{
value: 4,
label: 'aqua sky',
},
{
value: 5,
label: 'tigerlily',
},
{
value: 6,
label: 'blue turquoise',
},
];
// set value for default selection
const [selectedValue, setSelectedValue] = useState([
{ value: [] },
{ value: [] },
{ value: [] },
]);
// handle onChange event of the dropdown
const handleChange = (e, no) => {
setSelectedValue(
selectedValue.map((item) => {
return selectedValue.indexOf(item) === no
? { value: Array.isArray(e) ? e.map((x) => x.value) : [] }
: item;
})
);
};
return (
<div className="App">
<Select
className="dropdown"
placeholder="Select Option"
value={data.filter((obj) => selectedValue[0].value.includes(obj.value))} // set selected values
options={data} // set list of the data
onChange={(event) => handleChange(event, 0)} // assign onChange function
isMulti
isClearable
/>
<br />
<Select
className="dropdown"
placeholder="Select Option"
value={data.filter((obj) => selectedValue[1].value.includes(obj.value))} // set selected values
options={data} // set list of the data
onChange={(event) => handleChange(event, 1)} // assign onChange function
isMulti
isClearable
/>
<br />
<Select
className="dropdown"
placeholder="Select Option"
value={data.filter((obj) => selectedValue[2].value.includes(obj.value))} // set selected values
options={data} // set list of the data
onChange={(event) => handleChange(event, 2)} // assign onChange function
isMulti
isClearable
/>
{selectedValue && (
<div style={{ marginTop: 20, lineHeight: '25px' }}>
<div>
<b>Selected Value: </b> {JSON.stringify(selectedValue, null, 2)}
</div>
</div>
)}
</div>
);
}
export default App;
{selectedValue && (
<div style={{ marginTop: 20, lineHeight: '25px' }}>
<div>
<b>Selected Values: </b>
<span>{
selectedValue.map(item => item.value.length !== 0 ?
<li>{data.filter(data => data.value === item.value[0])[0].label}</li> :
<li>No value selected</li>
)
}</span>
</div>
</div>
)}

How to build a generic menu component?

I have to build a menu screen component that can be used later on easily. The component only has options in a list way.
const options = [
{
text: 'Option 1',
},
{
text: 'Option 2',
},
{
text: 'Option 3',
},
];
and I just map it inside the component.
const Menu = () => {
return (
<div>
{options.map((option, index) => (
<MenuOption text={option.text} index={index} />
))}
</div>
);
};
const MenuOption = ({ text, index }) => {
return (
<div>
<p>{text}</p>
</div>
);
};
So anyone can use this menu component by passing in the options data. What i want is for this component to also run functions corresponding to the option clicked. So we can easily pass the function that needs to be run as a prop to the component. The main question is that how do i relate/map the options with the corresponding function?
NOTE: I can't send the functions with the options data object in the props.
I mean you can just send one callback to the Menu component:
const Menu = ({ onOptionClick }) => {
return (
<div>
{options.map((option, index) => (
<MenuOption text={option.text} index={index} onClick={onOptionClick} />
))}
</div>
);
};
const MenuOption = ({ text, index, onClick }) => {
return (
<div onClick={() => { onClick(index, text, whatever) }}>
<p>{text}</p>
</div>
);
};

More generic way to set an objects value within React handleChange

I have a component in React, I need to take a value from the radio button being checked and then set that value within an object in my Formik values. If a different radio button is selected within the group I need to set the previously selected one to false, is there a standard way of doing this? I'm using an object within my Formik values as the field holds a date as well as the attribute from the radio button, you can see where I place the date into the object using handleTime, so I can't just null the field and place the new item in.
I'm currently doing the following in my component to update the Formik time_frame value.
import React, {Component} from 'react';
import {Col, Row} from 'react-bootstrap';
import Radio from "./radio";
export default class EventTimeFrame extends Component {
state = {
eventTimeFrame: [
{id: 1, value: "one_off", label: "ONE OFF", checked: false},
{id: 2, value: "recurring", label: "RECURRING", checked: false},
]
}
handleOccurance = value => {
let timeCopy = {...this.props.values.time_frame}
if (value.target.checked) {
if (value.target.value === "one_off") {
timeCopy[value.target.value] = true
timeCopy["recurring"] = false
} else {
timeCopy[value.target.value] = true
timeCopy["one_off"] = false
}
}
this.props.onChange("time_frame", timeCopy)
this.setState(prevState => ({
eventTimeFrame: prevState.eventTimeFrame.map(
el => el.value === value.target.value ? {...el, checked: true} : el
)
}))
};
handleTime = value => {
let timeCopy = {...this.props.values.time_frame}
timeCopy["start"] = new Date(value.target.value);
this.props.onChange("time_frame", timeCopy)
};
render() {
return (
<div>
<Row>
<Col>
<h4 className="ui centered question-header text-center">ONE OFF OR RECURRING EVENT?</h4>
</Col>
</Row>
<Row>
{
this.state.eventTimeFrame.map((timeFrame) => {
return (
<Radio name="time_frame" key={timeFrame.value}
onChange={this.handleOccurance} checked={timeFrame.checked} {...timeFrame} />
)
})
}
</Row>
<Row>
<Col>
<h4 className="question-header date-text">PLEASE ENTER THE FIRST DAY OF YOUR EVENT</h4>
</Col>
<Col>
<input type="date" className="form-control date" name="start"
onChange={this.handleTime}/>
</Col>
</Row>
</div>
)
}
}
I feel like there has to be a standard way of dealing with things like this
You're correct by suspecting there's a simpler way 😃 Some feedback:
Don't store the eventTimeFrame in state, a constant will do.
The standard way of using radio input values in Formik is to define one value in initialState for the entire group. Formik will set its value to the selected option.
Storing all options in values would have been fine if you were using checkboxes instead of radio buttons.
You wrote your own custom onChange handlers, but it would be simpler to just use Formik's provided onChange handlers. I only use my own handler if I have to, for example when formatting a value before setting it with setFieldValue()
See below:
Live Demo
// outside of component
const timeFrameTypes = [
{ id: "one_off", label: "ONE OFF" },
{ id: "recurring", label: "RECURRING" }
];
// in component's render function:
<Formik
initialValues={{
time_frame: {
type: "",
start: ""
}
}}
onSubmit={async (values) => {
// do something with values
}}
>
{({ handleSubmit }) => {
return (
<form onSubmit={handleSubmit}>
<div>
<Row>
<Col>
<h4 className="ui centered question-header text-center">
ONE OFF OR RECURRING EVENT?
</h4>
</Col>
</Row>
<Row>
{timeFrameTypes.map((timeFrameType) => {
return (
<Field
key={timeFrameType.id}
component={Radio}
name="time_frame.type"
id={timeFrameType.id}
label={timeFrameType.label}
/>
);
})}
</Row>
<Row>
<Col>
<h4 className="question-header date-text">
PLEASE ENTER THE FIRST DAY OF YOUR EVENT
</h4>
</Col>
<Col>
<Field name="time_frame.start">
{({ field }) => <input type="date" {...field} />}
</Field>
</Col>
</Row>
</div>
<br />
<button type="submit">Submit</button>
</form>
);
}}
</Formik>

How to display and handle dynamic checkoxes that are dependent on Task array value in the backend (Mongodb) in react js?

I working on a react project where I have requirement like,
I have array inside contain, 1 Object and 1 Array named Task[]
"contractor": [
{
"contractGivenBy": -1,
"contractorID": 0,
"contractorName": "contractor1",
"reviewedByAssigner": false,
"submitReviewToAssigner": false,
"tasks": [ 2, 4, 6 ],
"tasksDone": false
},
Now, I want to display the Tasks array as Checkboxes in the page.
That is nice, I displayed all checkboxes using map() method, But the problem is, How to handle (get values from those checkboxes) when user checked or unchecked the specific checkbox.
I'm using React functional component with React hooks.
Here is what is tried..
<form onSubmit={onSubmitHandler}>
{
projectData.contractor[0].tasks.map((task, index) => {
return (
<div style={{ flexDirection: "column" }}>
<FormControlLabel
control={
<Checkbox
checked={false}
value={task}
onChange={handleTask} />
}
label={`task ${task}`}
/>
</div>
)
})
}
<Button
type="submit"
style={{
backgroundColor:"rgba(25,123,189)",
color: "white"
}}>
Assgin
</Button>
</form>
UPDATED
Here you go , it uses react hooks with checkbox implementation, i have tweaked it a little with <input type /> but you will get the idea
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Checkbox = ({ type = "checkbox", name, checked = false, onChange }) => {
console.log("Checkbox: ", name, checked);
return (
<input type={type} name={name} checked={checked} onChange={onChange} />
);
};
const CheckboxExample = () => {
const [checkedItems, setCheckedItems] = useState({});
const handleChange = event => {
setCheckedItems({
...checkedItems,
[event.target.name]: event.target.checked
});
console.log("checkedItems: ", checkedItems);
};
const checkboxes = [
{
name: "check-box-1",
key: "checkBox1",
label: "Check Box 1"
},
{
name: "check-box-2",
key: "checkBox2",
label: "Check Box 2"
}
];
return (
<div>
<lable>Checked item name : {checkedItems["check-box-1"]} </lable> <br />
{checkboxes.map(item => (
<label key={item.key}>
{item.name}
<Checkbox
name={item.name}
checked={checkedItems[item.name]}
onChange={handleChange}
/>
</label>
))}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<CheckboxExample />, rootElement);

Categories

Resources