I am a new reacter. I have a problem when i use map and variables could you help me?
i don't know how to input the variables in options like value={name.value}
const info = [
{ key: "닉네임", value: "name" },
{ key: "지역", value: "area" },
{ key: "생일", value: "birthday" },
{ key: "키", value: "tall" },
{ key: "몸매", value: "body" },
{ key: "직업", value: "job" },
{ key: "회사", value: "company" },
{ key: "학교", value: "school" },
{ key: "학력", value: "background" },
{ key: "종교", value: "religion" },
{ key: "흡연", value: "smoking" },
{ key: "카카오 아이디", value: "kakaoid" }
];
<Grid container spacing={3}>
{info.map((info, index) => (
<Grid item xs={12} sm={6} key={index}>
<TextField
required
id={index}
name={info.value}
label={info.key}
value={}
onChange={}
fullWidth
/>
</Grid>
))}
</Grid>
I want to make it like that
<Grid item xs={12} sm={6} key={1}>
<TextField
required
id={1}
name={"name"}
label={"닉네임"}
value={name.value}
onChange={name.onChange}
fullWidth
/>
</Grid>
If you want to set the value for the each text field .
Define a state variable for each of the text-field (use name of the each text fields)and bind an on-change event.
In on-change bind an this and get the name & value , based on on-change set the value to the name state for each text field
Now pass the state to each of the text-field .
You should aware of state an props in react , on-change events.
For example
constructor(props){
super(props);
this.state = {
value:''
}
}
inputchange = (event) =>{
this.setState({
value:event.target.value
})
}
render(){
return (
<div className="todolist">
<input type="text" value={this.state.value} onChange={this.inputchange}/>
<input type="button" value="Submit" onClick={this.props.handleclick.bind(this,this.state.value)}/>
</div>
);
}
}
Related
I am writing some code for a ReactJS component to have an array of chips. I want each chip to be styled uniquely, so I set up a makeStyles class for each one. I was having trouble trying to figure out how to change the class for each tag. This is what I got so far:
const classes = useStyles();
const [chipData, setChipData] = React.useState([
{ key: 0, label: 'Heating' },
{ key: 1, label: 'Printing' },
{ key: 2, label: 'Resetting' },
{ key: 3, label: 'Idle' },
{ key: 4, label: 'Suspended' },
{ key: 5, label: 'Suspend in Progress' },
{ key: 6, label: 'Attention - Printer Connection Lost' },
{ key: 7, label: 'Attention - Filament Out' },
{ key: 8, label: 'Attention - Cooldown Failed' },
]);
return (
<Box display="flex" flexDirection="row" alignItems="flex-start" className={classes.container}>
{chipData.map((data) => {
return (
<div classes={classes.chipContainer}>
<li key={data.key}>
<Chip
label={data.label}
if (label === 'Heating') {
className={classes.heatingTag}
}
/>
</li>
</div>
);
})}
</Box>
);
}
export default PrinterStatusTags
So within the chip element, I have an if statement that is used to assign a specific class based on the label. My plan was to have an if statement for each label, but I am getting the following error:
Parsing error: Unexpected token
Any ideas how I can assign a class based on the chip?
Updated Answer
I would 2 things:
Add a new type property for every chip.
Create a mapper from the type (in the 1st point) to the classes
const classesMapper = {
first: classes.firstClass,
second: classes.secondClass
// ...
};
const [chipData, setChipData] = React.useState([
{ key: 0, label: 'Heating', type: 'first' },
{ key: 1, label: 'Printing', type: 'seocnd' },
// ....
]);
After you have the mapping between every chip to its type. Just render it:
return (
<Box display="flex" flexDirection="row" alignItems="flex-start" className={classes.container}>
{chipData.map((data) => {
return (
<div classes={classes.chipContainer}>
<li key={data.key}>
<Chip
label={data.label}
className={classesMapper[data.type]} />
</li>
</div>
);
})}
</Box>
);
Old Answer
You should write the code a little bit different:
Use className property and not the property class (nor classes)
Set the condition inside the className property. Please note that there are better ways to set the right class but for your case, that would be good enough.
This is the code as it should be:
<div classeName={classes.chipContainer}>
<li key={data.key}>
<Chip label={data.label} className={ label ==== 'Heating' && classes.heatingTag}/>
</li>
</div>
I am new to React. I'm using react-select and I've used the following code. The dropdown is displayed but I'm unable to see names and unable to view after selecting.
<Select
variant="outlined"
margin="normal"
fullWidth
value={this.state.selected}
options={RewardAutomationsList}
name="selected"
onChange={this.handleChange}
placeholder='None'
>
{RewardAutomationsList.map((option) => (
<option key={option.id} value ={option.name} label={option.name}>
{option.name}
</option>
))}
</Select>
handleChange = event => {
this.setState({
selected: event.name
});
};
The RewardAutomationsList looks like this:
RewardAutomationsList:
0:{name: "TEST 1 (INR 100)", id: "123"}
1:{name: "test 2 (INR 250)", id: "456"}
Can someone help with this?
same npm package use like this block code.
import React, { Component } from 'react'
import Select from 'react-select'
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const MyComponent = () => (
<Select options={options} />
)
react-select accepts an array of objects having label and value keys. Your option objects in RewardAutomationsList have id and name keys, so it can't be displayed. You need to change them.
Also, when you subscribe to change events with react-select's onChange prop, the callback function you provide receives the selectedOption, not the event.
The following should work:
const RewardAutomationsList = [
{ label: "TEST 1 (INR 100)", value: "123" },
{ label: "test 2 (INR 250)", value: "456" },
];
class App extends React.Component {
state = {
selected: null,
}
handleChange = (selectedOption) => {
this.setState({
selected: selectedOption,
});
};
render() {
return (
<React.Fragment>
<Select
fullWidth
margin="normal"
name="selected"
onChange={this.handleChange}
options={RewardAutomationsList}
placeholder="None"
value={this.state.selected}
variant="outlined"
/>
{/* It's not necessary and it's only here to show the current state */}
<pre>{JSON.stringify(this.state, null, 2)}</pre>
</React.Fragment>
);
}
}
I have this component:
import React from 'react';
const options = [
{ label: "Lifestyle", value: "lifestyle"},
{ label: "Area", value: "area" },
{ label: "Random", value: "random" }
];
const ChannelCategory = props =>
props.visible ? (
<div>
{props.title}
<ul>
{options.map((option) => (
<li key={option.value}>
<label>
{option.label}
<input
className={props.className}
name={props.name} // need to be different
selected={props.selected === option.value} // e.g. lifestyle === lifestyle
onChange={() => props.onChange(option.value)}
type="radio"
/>
</label>
</li>
))}
</ul>
</div>
) : null;
export default ChannelCategory;
I am rendering it on another page here in a .map:
let displayExistingChannels = null;
if (channels !== null){
displayExistingChannels = (
channels.map(channel => {
return (
<Grid key={channel.key} item style={styles.gridItem} justify="space-between">
<ChannelListItem
channel={channel}
isSaving={isSaving}
onDeleteChannelClick={onDeleteChannelClick}
key={channel.key}
onFormControlChange={onFormControlChange}
onUndoChannelClick={onUndoChannelClick}
/>
{channel.category}
<ChannelCategory
visible={true}
onChange={value => setCategoryName(value)}
title="Edit Category"
selected={channel.category}
name={channel.key} // unique for every channel
/>
</Grid>
)
})
)
}
I am using fake data for the map:
const fakeChannelData = setupChannels(
[{id: "2f469", name: "shopping ", readOnly: false, category: "lifestyle"},
{id: "bae96", name: "public", readOnly: true, category: "null"},
{id: "06ea6", name: "swimming ", readOnly: false, category: "sport"},
{id: "7e2bb", name: "comedy shows ", readOnly: false, category: "entertainment"}]);
const [channels, setChannels] = useState(fakeChannelData);
Please can someone tell me why when I add selected={channel.category} in my .map function it does not show the selected category preselected on the FE on page load? Not sure where I have gone wrong? Thanks!
checked is the correct attribute to use for input tag, not selected.
<input
...
checked={props.selected === option.value}
...
/>
ref: https://developer.mozilla.org/fr/docs/Web/HTML/Element/Input/radio
I have a list of chat room channels for people to talk i.e there is a lifestyle channel, shopping channel, pets channel etc.
I am now trying to categorise each channel to make it easier for the user to find what they want. In order to do so, on creation of a chatroom channel I need the user to select which category the channel they are creating best fits into. A bit like YouTube does when you upload a video.
So far I have created a separate component which is a list of checkboxes with the different categories the user can put their channel into:
import React from 'react';
const options = [
{ label: "Lifestyle", value: "lifestyle"},
{ label: "Area", value: "area" },
{ label: "Random", value: "random" },
{ label: "Comedy", value: "comedy" },
{ label: "Entertainment", value: "entertainment" }
];
const ChannelCategory = (props) => {
return (
<div>
{props.title}
<ul>
{options.map((option) => (
<li key={props.key}>
<label>
{option.label}
<input
className={props.className}
name="test"
checked={props.checked}
onChange={() => props.onChange(option.value)}
type="checkbox"
/>
</label>
</li>
))}
</ul>
</div>
)
};
export default ChannelCategory;
I am using the above component on the page below, I would like that when the user selects just ONE of the options only ONE input box is checked, however at the moment when I click ONE input box for instance lifestyle they ALLLL get checked and for every single channel too:( Any ideas why?
const [checked, setCheckBoxChecked] = useState(false);
[...]
const onAddCategory = (value) => {
console.log(value);
if (value === "lifestyle") {
setCheckBoxChecked(checked => !checked);
}
if (value === "area") {
setCheckBoxChecked(checked => !checked);
}
if (value === "random") {
setCheckBoxChecked(checked => !checked);
}
if (value === "comedy") {
setCheckBoxChecked(checked => !checked);
}
};
[...]
const options = [
{ label: "Lifestyle", value: "lifestyle"},
{ label: "Area", value: "area" },
{ label: "Random", value: "random" },
{ label: "Comedy", value: "comedy" },
{ label: "Entertainment", value: "entertainment" }
];
return (
<form noValidate autoComplete='off' onSubmit={onSubmit}>
<Card style={styles.card}>
<CardContent>
<Box padding={3}>
<FormLegend title={`${formTitle} (${channels.length})`} description={formDescription} />
<Box marginTop={3} width='50%'>
<Grid container direction='column' justify='flex-start' alignItems='stretch' spacing={1}>
{channels.map(channel => {
return (
<Grid key={channel.key} item style={styles.gridItem} justify="space-between">
<ChannelListItem
channel={channel}
isSaving={isSaving}
onDeleteChannelClick={onDeleteChannelClick}
key={channel.Key}
onFormControlChange={onFormControlChange}
onUndoChannelClick={onUndoChannelClick}
/>
<ChannelCategory
key={channel.key}
options={options}
onChange={value => onAddCategory(value)}
title="Add your chatroom to a category so that users can find it easily"
checked={checked}
/>
</Grid>
)
})}
[...]
</Grid>
</Grid>
</Box>
</Box>
</CardContent>
</Card>
</form>
);
Instead of storing true or false inside the checked variable, you should store the value inside of checked. Like this:
const onChangeAttribute = (value) => {
console.log(value);
setCheckBoxChecked(value);
};
And now while rendering the checkbox you should check if checked is equal to the name of that checkbox like this:
<input
className={props.className}
name={option.value}
checked={props.checked === option.value}
onChange={() => props.onChange(option.value)}
type="checkbox"
/>
This should resolve your issue.
Use an array to store all checked boxes and in your ChannelCategory check if the current value exists in the checked array then set checked to true for that checkbox. If you want to select only one category use radio buttons
const {useState, useEffect} = React;
const options = [
{ label: "Lifestyle", value: "lifestyle" },
{ label: "Area", value: "area" },
{ label: "Random", value: "random" },
{ label: "Comedy", value: "comedy" },
{ label: "Entertainment", value: "entertainment" }
];
const ChannelCategory = props => {
return (
<div>
{props.title}
<ul>
{props.options.map(option => (
<li key={props.key}>
<label>
{option.label}
<input
className={props.className}
name={option.value}
checked={props.checked.includes(option.value)}
onChange={e => props.onChange(e.target.checked, option.value)}
type="checkbox"
/>
</label>
</li>
))}
</ul>
</div>
);
};
function App() {
const [checked, setCheckBoxChecked] = useState([]);
const onAddCategory = (isChecked, value) => {
const temp = [...checked];
if (isChecked) {
temp.push(value);
setCheckBoxChecked(temp);
return;
}
setCheckBoxChecked(temp.filter(item => item !== value));
};
return (
<div className="App">
<ChannelCategory
key={"channel.key"}
options={options}
onChange={onAddCategory}
title="Add your chatroom to a category so that users can find it easily"
checked={checked}
/>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<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="react"></div>
Radio buttons example
I am learning react by myself, and I am having a hard time doing something thought it would be simple.
In summary, I have a menu with a few items.
I want to be able to select that menu item and when that happens, open a form next to it, the form has inputs, and those input will be prefilled in case there's a saved value for it.
I want, if possible, to hide the editable form in case I click away from the form.
I am not sure how to do that. I have been playing with the props, and react is complaining about uncontrollable and controllable components. I read about it and I get and. Now I am not sure what is the best way to do this. I don't need a "hack" in case my solution is not the right way to do it. I am really looking for how people would handle similar problem in an elegant way in React.
Here's parts of the code I was writing, using material-ui-next
class EditMenu extends React.Component {
constructor(props) {
super(props);
console.log(props);
const itemsInfo = [
{id: 11 ,
title: 'title 1',
description: 'desc 1'
},
{id: 22 ,
title: 'title 2',
description: 'desc 2'
},
{id: 33 ,
title: 'title 3',
description: 'desc 3'
},
];
let itemId = this.props.selectedItem;
let item = _.find(itemsInfo, {id:itemId});
this.state = {
value: '',
item: item,
itemName: '',
itemDescription: ''
};
}
handleitemNameSetting = (event) => {
event.preventDefault();
debugger;
this.setState({
itemName: event.target.value
});
}
render() {
return (
<div className="form-container">
<form >
<TextField
id="item-name"
label="item Name"
margin="normal"
onChange={this.handleItemNameSetting}
value={this.state.item.title}
/>
<br />
<TextField
id="dish-desc"
label="item Description"
margin="normal"
value={this.state.item.description}
/>
<br />
<TextField
className="value-field-container"
label="value"
type="number"
hinttext="item value" />
</form>
</div>
);
}
}
class MenuList extends React.Component {
state = { editMenuOpen: false };
handleClick = (id,event, item, ind) => {
this.setState({editMenuOpen: true, selectedItem: id});
};
render() {
const { classes } = this.props;
const menuItems = [
{id: 11 ,
title: 'title 1'
},
{id: 22 ,
title: 'title 2'
},
{id: 33 ,
title: 'title 3'
},
];
return (
<div className={classes.root}>
<Grid container spacing={24}>
<Grid item xs={2}>
<div>
<List
component="nav"
subheader={<ListSubheader component="div">Lunch Menu</ListSubheader>}
>
{menuItems.map(item => (
<ListItem button key={`${item.id}`} onClick= { () => this.handleClick(item.id)}>
<ListItemText primary={`${item.title}`} />
</ListItem>
))}
</List>
</div>
</Grid>
<Grid item xs>
<div>
{ this.state.editMenuOpen ? <EditMenu selectedItem={this.state.selectedItem}></EditMenu> : null }
</div>
</Grid>
</Grid>
</div>
);
}
}
I would add an onClick event handler on the outermost parent element, that triggers a setState and changes the editMenuOpen to false.
Let's assume it's called handleCloseMenuClick.
But i would also need to add an event handler on my form itself that stops the event from handleCloseMenuClick from triggering when i click my form using event.stopPropagation()
Check the console in this example and see the difference when you remove the event.stopPropagation()