React add css class dynamically - reactjs

I have a set of tabs and I want to apply different class to the selected tab:
My component:
constructor(props) {
super(props);
this.state = {
activeTab: false,
};
}
setActiveTab = ()=> {
this.state.activeTab=true
}
render() {
return (
<HtmlPage>
<div className="tab">
<InternalLink to={`/settings/user-profile`} >
<div className="tablinks">Nutzerprofil</div>
</InternalLink>
<InternalLink to={`/settings/company-profile`} >
<div className={this.state.activeTab ? 'active':'tablinks'} onClick={this.setActiveTab}>Firmenprofil</div>
</InternalLink>
<InternalLink to={`/settings/user-profile`} >
<div className="tablinks">Nutzerverwaltung</div>
</InternalLink>
</div>
<div className="content">
{this.props.children}
</div>
</HtmlPage>
);
}
And my css:
/* Style the tab */
div.tab {
padding-top: 1%;
overflow: hidden;
border: 1px solid #ccc;
}
/* Style the buttons inside the tab */
div.tab .tablinks {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 20px;
}
/* Change background color of buttons on hover */
div.tab .tablinks:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
div.tab .active {
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 20px;
background-color: #ccc;
}
However, this just sets the class to active for the first clicked tab and not each time I select another tab. How can I fix it?

Set a name for the active tab on click, and then compare while setting the class like
constructor(props) {
super(props);
this.state = {
activeTab: '',
};
}
setActiveTab = (val, e)=> {
this.setState({activeTab: val})
}
<div className="tab">
<InternalLink to={`/settings/user-profile`} >
<div className={this.state.activeTab == 'user-profile' ? 'active':'tablinks'} onClick={this.setActiveTab.bind(this, 'user-profile')}>Nutzerprofil</div>
</InternalLink>
<InternalLink to={`/settings/company-profile`} >
<div className={this.state.activeTab == 'company-profile ? 'active':'tablinks'} onClick={this.setActiveTab.bind(this, 'company-profile')}>Firmenprofil</div>
</InternalLink>
<InternalLink to={`/settings/user-profile`} >
<div className={this.state.activeTab == 'user-profile1 ? 'active':'tablinks'} onClick={this.setActiveTab.bind(this, 'user-profile2')}>Nutzerverwaltung</div>
</InternalLink>
</div>

Related

Input checkbox didn't work what I expected

I tried to make an input checkbox when I click the input checkbox, it should be displayed a check image like this.
However, it didn't show the checkbox and I am not sure how to check that the input box was checked or not. Could you help me with what part do I missed and where is something wrong?
I really appreciate your help!
This is CSS inputl and label part
.colors {
display: flex;
flex-direction: column;
span {
margin-bottom: 20px;
}
.colorLists {
margin-left: 10px;
display: flex;
flex-wrap: wrap;
.colorLayout {
display: flex;
flex-direction: column;
position: relative;
width: 33%;
height: 80px;
flex-shrink: 0;
align-items: center;
justify-content: center;
.checkboxLabel {
background-color: beige;
border: 1px solid #ccc;
border-radius: 50%;
cursor: pointer;
height: 28px;
left: 0;
position: absolute;
top: 40;
width: 28px;
&:after {
border: 2px solid #fff;
border-top: none;
border-right: none;
content: '';
height: 6px;
left: 7px;
opacity: 0;
position: absolute;
top: 8px;
transform: rotate(-45deg);
width: 12px;
// opacity: 0.2;
}
}
input[type='checkbox'] {
visibility: hidden;
}
input[type='checkbox']:checked {
& + label {
background-color: beige;
border-color: beige;
&:after {
opacity: 1;
}
}
}
.productColor {
margin-top: 70px;
font-size: 13px;
margin-right: 21px;
}
}
}
}
.sizes {
.HorizontalLine {
margin-top: 25px;
}
.span {
}
.sizeLists {
margin-top: 20px;
margin-bottom: 20px;
button {
margin: 5px;
width: 44px;
height: 32px;
background-color: white;
border: 1px solid silver;
border-radius: 15%;
}
}
}
This is js part
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input type="checkbox" />
<label
className="checkboxLabel"
for="checkbox"
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
In react you have to set the htmlFor property for the label instead of for.
The value should be the same as the id from the input.
Then you can add a value property for the input which is used for adding/removing the item in the list of selected items.
For this purpose a handleChange function can be defined.
const [selectedItems, setSelectedItems] = useState([]);
function handleChange(e) {
let newSelected = [];
if (selectedItems.includes(e.target.value)) {
newSelected = selectedItems.filter((item) => item !== e.target.value);
} else {
newSelected = [...selectedItems, e.target.value];
}
setSelectedItems(newSelected);
}
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
EDIT: Since you are using a class component it can be rewrittenlike this:
export default class CheckboxListComponent extends Component {
constructor(props) {
super(props);
this.state = { selectedItems: [] };
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
let newSelected = [];
if (this.state.selectedItems.includes(e.target.value)) {
newSelected = this.state.selectedItems.filter(
(item) => item !== e.target.value
);
} else {
newSelected = [...this.state.selectedItems, e.target.value];
}
this.setState({ selectedItems: newSelected });
}
render() {
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={this.handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={this.state.selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
}
}
You must tell react that your input is checked so that your CSS will apply it. selected ids must be kept in a place for future existence check. in the following code, I named this array selecetedIdx.
You also need to add idx on selection(via onChange event handler) or wrap them all in form and add them via extra dom attribute.
class Main extends Component {
// initialize selectedIdx with [] in your state (esp constructor)
// e.g. this.state = {/* rest of state, */ selectedIdx: []}
render() {
return (
{COLOR_LISTS.map((color, idx) => {
return (
// ...
<input
type="checkbox"
checked={selectedIdx.includes(idx)}
onChange={() => this.setState(state => ({
selectedIdx: [...state.selectedIdx, idx]
}))}
/>
// ...
)}
)
}
Your checkbox element needs name and value properties and would normally be a child of the <form> element.

React nested loop bug

I am trying to build on the beginner react tutorial.
The below code compiles successfully in terminal. Note, only the lines from "Square" downwards are directly relevant, I think.
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const size = 30
class DropDown extends React.Component{
algorithm_states = {
alg:0,
}
algClick(i){
this.algorithm_states.alg = i;
}
startResetClick(i){
switch(i){
default:
case 0:
//enable disable buttons on grid
//run relevent processes bases on algorithm state machine
break;
case 1:
// clear grid and matrix
// enable buttons on grid
break;
}
}
render(){
return(
<header>
<button className = "main">
Main
</button>
<div className="dropdown">
<span>Choose Rule</span>
<div className="dropdown-content">
{/* algorithms mapped to their indicies in list */}
<button
onClick={() => this.algClick(0)}
>Game Of Life</button>
<button
onClick={() => this.algClick(1)}
>Langtons Ant</button>
</div>
</div>
{/* start button mapped to 0, reset button mapped to 1 */}
<button
className = "start"
onClick={() => this.startResetClick(0)}
>START</button>
<button
className = "stop"
onClick={() => this.startResetClick(1)}
>RESET</button>
</header>
)
}
}
class Square extends React.Component {
keys = {
x:null,
y:null,
}
render() {
return (
<button className="square" key = {this.keys.x + this.keys.y}>
</button>
);
}
}
class Board extends React.Component{
renderSquare(x, y) {
return (
<Square
keys = {[x,y]}/>
);
}
render(){
const rows = [], cols = [];
for(var i = 0; i < size; i++){
rows[i] = i;
cols[i] = i;
}
return(
<div>
{[...rows].map((x) => {
return (
<div className="board-row" key={x}>
{[...cols].map((y) => this.renderSquare(x,y))}
</div>
)
})
}
</div>
)
}
}
class Game extends React.Component {
render() {
return (
<div className="game">
<header className = "header">
<DropDown/>
</header>
<body>
<div className="game-board">
<Board />
</div>
</body>
</div>
);
}
}
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
index.css
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol, ul {
padding-left: 30px;
}
.header{
background: "black";
}
.main {
position: absolute;
left: 5%
}
.game-board{
position: absolute;
top: 20%;
left:30%;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 10px;
font-weight: bold;
line-height: 15px;
height: 15px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 15px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
}
.dropdown {
position: absolute;
top: 20%;
left: 5%;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 12px 16px;
z-index: 1;
}
.dropdown:hover .dropdown-content {
display: block;
}
.start{
position: absolute;
right: 15%;
}
.stop{
position: absolute;
right: 5%;
}
But in browser, I get the error
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `Board`. See https://reactjs.org/link/warning-keys for more information.
Square#http://localhost:3000/static/js/main.chunk.js:249:5
Board#http://localhost:3000/static/js/main.chunk.js:268:1
div
body
div
Game#http://localhost:3000/static/js/main.chunk.js:308:1
And I'm not sure what it's about, since I'm pretty sure all the keys I have provided are unique.
Anyone got any ideas???
Cheers
K
You need to render each Square component with a key at the map level:
render(){
const rows = [], cols = [];
for(var i = 0; i < size; i++){
rows[i] = i;
cols[i] = i;
}
return(
<div>
{[...rows].map((x) => {
return (
<div className="board-row">
{[...cols].map((y) => (
<Square keys={[x,y]} key={`x-y`} />
))}
</div>
)
})
}
</div>
)
}
}
See the reference on the docs

Why is git pages rendering my page different then in local?

I'm rather new to whole react thing, going through courses on FCC. My problem come from CSS/SCSS itself. I tried ordinary CSS and SCSS. My page is done in React. The page is also hosted on codepen. All three versions are the same, codepen, git and local and yet CSS is somewhat different between them. My previous projects who are also hosted on these platforms and in local have also the same CSS but they look identical. Difference between local and codepen's version isn't that drastic, but between local>codepen>github is more than noticeable as you descend. Do GitHub ignores/renders? or what, React differently? This question should also apply to codepen.
My codepen
My git page
My repoToProject
Image of localhost:
html from codepen:
<div id="root"></div>
scss from codepen:
$position: absolute;
$percentage: 100%;
$color: whitesmoke;
$car: auto;
#import url("//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css");
.btn1 {
position: $position;
bottom: -30px;
left: 51.3%;
z-index: 999;
background-color: $color;
border: 1px solid gray;
color: aqua;
}
#root {
width: $percentage;
}
body,
html {
height: $percentage;
}
body {
background-color: $color;
background-image: url("../images/react1.png");
background-repeat: no-repeat;
background-size: $car;
background-position: center bottom;
overflow: hidden;
}
.grid-container {
display: grid;
grid-template-columns: 50% 50%;
background-color: $color;
padding: 10px;
grid-gap: 15px;
width: $percentage;
grid-template-rows: 30px 25px 98%;
}
.grid-item {
text-align: center;
}
#inner2 {
padding-left: 20px;
padding-right: 25px;
border-bottom: 15px solid #d6e9c6;
padding-bottom: 55px;
background-color: #fcf8e3;
width: $percentage;
margin-left: $car;
margin-right: $car;
position: $position;
top: 0px;
left: 0px;
height: $percentage;
min-height: 20%;
max-height: $percentage;
}
#editor {
width: $percentage;
background-color: white;
resize: none;
color: #495057;
border: 1px solid #ced4da;
border-radius: 0.25rem;
overflow-y: $car;
max-height: $percentage;
min-height: 40px;
margin-bottom: 40px;
}
#preview {
width: 98.9%;
background-color: white;
border-radius: 0.25rem;
border: 1px solid #ced4da;
overflow-y: $car;
max-height: $percentage;
min-height: 40px;
margin-bottom: 40px;
}
#item1,
#item2 {
font-family: "Russo One";
font-style: oblique;
font-weight: bold;
font-size: 2em;
margin-bottom: 10px;
padding-bottom: 0px;
width: $percentage;
background-color: #fcf8e3;
min-height: 50px;
border-bottom: none;
padding-top: 10px;
}
.insignia {
letter-spacing: 5px;
-webkit-transition: letter-spacing 1s;
transition: letter-spacing 1s;
}
.insignia:hover {
letter-spacing: 13px;
cursor: pointer;
}
.ui-resizable-s {
cursor: row-resize;
}
textarea:focus,
input:focus {
outline: none;
}
#arrow {
background-color: #dff0d8;
width: $percentage;
height: 15px;
position: $position;
bottom: -12px;
padding-left: 0px;
padding-right: 0px;
font-size: 1.5em;
border-bottom: 1px solid #d6e9c6;
text-align: center;
}
.glyphicon {
top: -4px;
left: 4px;
color: gray;
-ms-transform: scale(1, 0.6); /* IE 9 */
-webkit-transform: scale(1, 0.6); /* Safari */
transform: scale(1, 0.6);
}
#media screen and (max-height: 600px) {
#inner2 {
height: 90vh !important;
}
}
#eraser {
text-align: center;
grid-column: 1 / 3;
z-index: 2;
line-height: 10px;
margin-left: $car;
margin-right: $car;
}
/*Additional styling*/
td,
th {
border: 2px solid #224b4b;
padding-left: 5px;
padding-right: 5px;
}
.label {
position: $position;
top: -10px;
left: 0px;
min-width: $percentage;
z-index: 999;
}
.preview-editor {
position: fixed;
top: 55px;
left: 0px;
min-width: $percentage;
height: $percentage;
z-index: 999;
}
h1 {
border-bottom: 2px solid #224b4b;
}
h2 {
border-bottom: 1px solid #224b4b;
}
code {
background-color: #d6e9c6;
color: #e83e8c !important;
}
blockquote {
border-left: 2px solid black;
padding-left: 5px;
margin-left: 25px;
}
#media only screen and (max-width: 768px) {
img {
width: 100%;
}
#ggED {
text-align: left;
}
#ggPrev {
text-align: right;
}
.insignia,
.insignia:hover {
letter-spacing: 0px;
font-size: 1em;
}
}
js from codepen:
var renderer = new marked.Renderer();
renderer.link = function(href, title, text) {
return (
'<a target="_blank" href="' +
href +
'" title="' +
title +
'">' +
text +
"</a>"
);
};
marked.setOptions({
breaks: true,
renderer: renderer,
sanitize: true
});
class DisplayMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
markdown: defaultMarkdown,
erase: false,
goFull: false,
headViewKlasa: "grid-item",
headEdKlasa: "grid-item",
editorKlasa: "",
previewKlasa: "",
stilPreview: {},
stilEditor: {},
attr: "Click on me for fullscreen",
inner2H: "",
h2Inner: false
};
this.handleChange = this.handleChange.bind(this);
this.eraseFields = this.eraseFields.bind(this);
this.inner2Height = this.inner2Height.bind(this);
}
eraseFields() {
this.setState({
erase: true
});
if (this.state.erase === false) {
this.setState({
markdown: ""
});
}
if (this.state.erase === true) {
this.setState({
markdown: defaultMarkdown,
erase: !this.state.erase
});
}
}
componentDidMount() {
this.node = ReactDOM.findDOMNode(this);
$(this.node).resizable({
handles: "s",
minHeight: 170
});
document
.querySelector(".ui-resizable-handle.ui-resizable-s")
.setAttribute(
"title",
"Double click on me or pull me down to full height"
);
}
inner2Height() {
if (this.state.h2Inner === false) {
this.setState({
inner2H: "100%",
h2Inner: true
});
}
if (this.state.h2Inner === true) {
this.setState({
inner2H: "",
h2Inner: false
});
}
}
fullScreen(clicked_id) {
if (clicked_id === "ggEd" && this.state.goFull === false) {
this.setState({
headEdKlasa: this.state.headEdKlasa + " label",
attr: "Click again to go back!",
editorKlasa: "preview-editor",
stilPreview: { display: "none" },
stilEditor: { paddingTop: "0px" },
goFull: true
});
}
if (clicked_id === "ggEd" && this.state.goFull === true) {
this.setState({
headEdKlasa: this.state.headEdKlasa.substr(0, 9),
attr: "Click on me for fullscreen",
editorKlasa: "",
stilPreview: { display: "block" },
stilEditor: { paddingTop: "10px" },
goFull: !this.state.goFull
});
}
if (clicked_id === "ggPrev" && this.state.goFull === false) {
this.setState({
headViewKlasa: this.state.headViewKlasa + " label",
attr: "Click again to go back!",
previewKlasa: "preview-editor",
stilEditor: { display: "none" },
stilPreview: { paddingTop: "0px" },
goFull: true
});
}
if (clicked_id === "ggPrev" && this.state.goFull === true) {
this.setState({
headViewKlasa: this.state.headViewKlasa.substr(0, 9),
attr: "Click on me for fullscreen",
previewKlasa: "",
stilEditor: { display: "block" },
stilPreview: { paddingTop: "10px" },
goFull: !this.state.goFull
});
}
}
handleChange(event) {
this.setState({
markdown: event.target.value
});
}
render() {
const btnText = this.state.erase ? "Populate" : "Erase";
const handleClick = e => this.fullScreen(e.target.id);
return (
<div
id="inner2"
className="grid-container animated zoomIn"
style={{ height: this.state.inner2H }}
onDoubleClick={this.inner2Height}
>
<EditorHead
id={"item1"}
style={this.state.stilEditor}
className={this.state.headEdKlasa}
onClick={handleClick}
title={this.state.attr}
/>
<PreviewHead
id={"item2"}
style={this.state.stilPreview}
className={this.state.headViewKlasa}
onClick={handleClick}
title={this.state.attr}
/>
<BtnEraser
id={"eraser"}
onClick={this.eraseFields}
type={"button"}
className={"btn btn-danger btn-lg"}
title={"Erase & populate both fields"}
value={btnText}
/>
<Editor
id={"editor"}
onChange={this.handleChange}
className={this.state.editorKlasa}
value={this.state.markdown}
placeholder={"Enter ... some kind a text!? ..."}
title={
"This is rather obvious isn't it? It's editor window Sherlock :D"
}
/>
<Preview
id={"preview"}
className={this.state.previewKlasa}
dangerouslySetInnerHTML={{
__html: marked(this.state.markdown, { renderer: renderer })
}}
title={"It's a preview window, Sherlock ;)"}
/>
<Arrow id={"arrow"} />
</div>
);
}
}
/*class Inner2 extends React.Component{
render(){
return (
<div id={this.props.id} className={this.props.className} style={this.props.style} onDoubleClick={this.props.onDoubleClick}>Editor:</div>
);
}
}*/
class EditorHead extends React.Component {
render() {
return (
<h1
id={this.props.id}
style={this.props.style}
className={this.props.className}
onClick={this.props.onClick}
>
<span className="insignia" title={this.props.title} id="ggEd">
Editor:
</span>
</h1>
);
}
}
class PreviewHead extends React.Component {
render() {
return (
<h1
id={this.props.id}
style={this.props.style}
className={this.props.className}
onClick={this.props.onClick}
>
<span className="insignia" title={this.props.title} id="ggPrev">
Previewer:
</span>
</h1>
);
}
}
class BtnEraser extends React.Component {
render() {
return (
<button
id={this.props.id}
onClick={this.props.onClick}
type={this.props.type}
className={this.props.className}
title={this.props.title}
>
{this.props.value}
</button>
);
}
}
class Editor extends React.Component {
render() {
return (
<textarea
id={this.props.id}
onChange={this.props.onChange}
className={this.props.className}
value={this.props.value}
placeholder={this.props.placeholder}
title={this.props.title}
/>
);
}
}
class Preview extends React.Component {
render() {
return (
<div
id={this.props.id}
className={this.props.className}
dangerouslySetInnerHTML={this.props.dangerouslySetInnerHTML}
title={this.props.title}
/>
);
}
}
class Arrow extends React.Component {
render() {
return (
<div id={this.props.id}>
<Glyph className={"glyphicon glyphicon-align-justify"} />
</div>
);
}
}
class Glyph extends React.Component {
render() {
return <span className={this.props.className} />;
}
}
ReactDOM.render(<DisplayMessages />, document.getElementById("root"));

react Semantic-UI - multi-select checkbox drop-down

i want to built an multi select checkbox dropdown in react with es6
my requirement is as below specified in image
I tried doing this click here but it is not working.
You can use one parent component that will keep values in its state and toggle list items. Then you can create component for each list item that will keep active property in state that you can toggle on click.
class ListItem extends React.Component {
constructor(props) {
super(props);
this.state = {active: false}
}
render() {
return (
<a
onClick={() => {
this.setState(prevState => {
let newState = !prevState.active;
this.props.handleClick(newState, this.props.value);
return {active: newState}
})
}}
className={!this.state.active ? '' : 'selected'}
href="#">
{this.props.value}</a>
)
}
}
class Select extends React.Component {
constructor(props) {
super(props);
this.state = {
showList: false,
value: []
}
this.handleItemClick = this.handleItemClick.bind(this)
}
componentDidMount() {
document.addEventListener('mousedown', (e) => {
if(!this.node.contains(e.target)) {
this.setState({showList: false})
}
})
}
componentWillUnmount() {
document.removeEventListener('mousedown');
}
renderValue() {
let {value} = this.state;
if(!value.length) return "Select..."
else return value.join(', ')
}
toggleList() {
this.setState(prevState => ({showList: !prevState.showList}))
}
handleItemClick(active, val) {
let {value} = this.state;
if(active) value = [...value, val]
else value = value.filter(e => e != val);
this.setState({value})
}
render() {
return (
<div
ref={node => this.node = node}
className="select">
<button onClick={this.toggleList.bind(this)}>
<span className="select_value">
{this.renderValue()}
</span>
</button>
<div
className={"select_list " + (!this.state.showList && 'hide')}>
<ListItem handleClick={this.handleItemClick} value="Lorem" />
<ListItem handleClick={this.handleItemClick} value="Ipsum" />
<ListItem handleClick={this.handleItemClick} value="Dolor" />
</div>
</div>
)
}
}
ReactDOM.render(
<Select />,
document.getElementById('container')
);
button {
background: white;
width: 100%;
padding: 10px 15px;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
cursor: pointer;
text-align: left;
}
.select_list {
width: 100%;
background: white;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
}
.select_list a {
padding: 10px 15px;
display: flex;
color: black;
text-decoration: none;
position: relative;
align-items: center;
}
.select_list a:before {
width: 15px;
height: 15px;
content: '';
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
margin-right: 10px;
display: block;
}
.select_list a.selected:before {
background: #0493D1;
content: '✓';
color: white;
font-size: 11px;
text-align: center;
line-height: 15px;
}
.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
Semantic-UI React Approach
After much digging, I found an old conversation between eugenetumachov and Semantic-UI developers(?). One of the users provided incredibly helpful code that answers this question using Semantic-UI's Dropdown component.
This is done by making use of Dropdown's Dropdown.Menu and Dropdown.Item. Then looping through your options via map to create checkboxes. The only downside is that the workaround does not seem to allow scrolling and will require more CSS. Additionally, based on CSS the checkbox items' background color may turn transparent if you double-click on the dropdown, and the dropdown will collapse on mouse hover. You can bypass the transparency issue by using a class or style property for your Dropdown.Menu and Dropdown.Item.
Semantic-UI developer's response to this type of question appears to be a flat "no" or a
Active items are automatically removed from the Dropdown menu. So you cannot show a "checked" state for an item in the menu.
You could create a similar component out of an Input as a trigger for
a Popup containing a Menu or List of Checkboxes.
Are dropdowns with checkboxes possible? #2417
eugenetumachov's workaround

React conditionally opening different divs

I am trying to conditionally open divs two and three, take a look at following snippet. showThird works correct however, showSecond has no effect? Basically on showSecond div-one shrinks to 50% width and div-two appears in rest 50%. Similar with div-third.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showSecond: false,
showThird: false
}
this.showDivTwo = this.showDivTwo.bind(this)
this.showDivThree = this.showDivThree.bind(this)
}
showDivTwo() {
this.setState(prevState => ({showThird: false, showSecond: !prevState.showSecond}))
console.log(this.state)
}
showDivThree() {
this.setState(prevState => ({ showSecond: false, showThird: !prevState.showThird}))
console.log(this.state)
}
render() {
return (
<div className={'wrapper' + (this.state.showSecond ? ' show' : '', this.state.showThird ? ' show' : '')}>
<div className="one">one
{/* Show second */}
<div>
<button onClick={this.showDivTwo}>{this.state.showSecond ? 'hideSecond' : 'showSecond'}</button>
</div>
{/* Show third */}
<div>
<button onClick={this.showDivThree}>{this.state.showThird ? 'hideThird' : 'showThird'}</button>
</div>
</div>
<div className="three">three
<div>
<button onClick={this.showDivThree}>{this.state.showThird ? 'hideThird' : 'showThird'}</button>
</div>
</div>
<div className="two">two
<div>
<button onClick={this.showDivTwo}>{this.state.showSecond ? 'hideSecond' : 'showSecond'}</button>
</div>
</div>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
.wrapper {
overflow: hidden;
white-space: nowrap;
}
.one, .two, .three {
background: #333;
border: 2px solid #787567;
box-sizing: border-box;
color: #fff;
display: inline-block;
font-family: arial;
overflow: hidden;
padding: 20px;
text-align: center;
transition: border 0.2s, padding 0.2s, width 0.2s;
min-height: 50vh;
}
.one {
width: 100%;
}
.two {
border-width: 2px 0;
padding: 20px 0;
width: 0;
}
.three {
border-width: 2px 0;
padding: 20px 0;
width: 0;
}
.show .one, .show .two, .show .three {
border-width: 2px;
padding: 20px;
width: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
What am I doing wrong here?
Changes:
1- use this condition:
className={'wrapper' + (this.state.showSecond || this.state.showThird ? ' show' : '')}
2- Use one more class hide, and put the check on className, apply that class if you want to hide the div otherwise apply class two or three.
Check the working code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showSecond: false,
showThird: false
}
this.showDivTwo = this.showDivTwo.bind(this)
this.showDivThree = this.showDivThree.bind(this)
}
showDivTwo() {
this.setState(prevState => ({showThird: false, showSecond: !prevState.showSecond}))
console.log(this.state)
}
showDivThree() {
this.setState(prevState => ({ showSecond: false, showThird: !prevState.showThird}))
console.log(this.state)
}
render() {
return (
<div className={'wrapper' + (this.state.showSecond || this.state.showThird ? ' show' : '')}>
<div className="one">
one
<div>
<button onClick={this.showDivTwo}>{this.state.showSecond ? 'hideSecond' : 'showSecond'}</button>
</div>
<div>
<button onClick={this.showDivThree}>{this.state.showThird ? 'hideThird' : 'showThird'}</button>
</div>
</div>
<div className={this.state.showThird?"three":'hide'}>
three
<div>
<button onClick={this.showDivThree}>{this.state.showThird ? 'hideThird' : 'showThird'}</button>
</div>
</div>
<div className={this.state.showSecond ? "two" : 'hide'}>two
<div>
<button onClick={this.showDivTwo}>{this.state.showSecond ? 'hideSecond' : 'showSecond'}</button>
</div>
</div>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
.wrapper {
overflow: hidden;
white-space: nowrap;
}
.hide, .one, .two, .three {
background: #333;
border: 2px solid #787567;
box-sizing: border-box;
color: #fff;
display: inline-block;
font-family: arial;
overflow: hidden;
padding: 20px;
text-align: center;
transition: border 0.2s, padding 0.2s, width 0.2s;
min-height: 50vh;
}
.one {
width: 100%;
}
.hide {
border-width: 2px 0;
padding: 20px 0;
width: 0;
}
.show .one, .show .two, .show .three {
border-width: 2px;
padding: 20px;
width: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Resources