Konrad Uciechowski Konrad Uciechowski - 6 months ago 26
React JSX Question

Show new component on Click on specific element of Component

I'am learning a reactJS and I created a calendar along a tutorial. Right now I want to improve it and display hours on click I want to show new component (Hours) with hours when I click on small component (Day) that is inside a Bigger component (calendar) Right now it doesn't work properly because I can render new Component when I click on every part of Calendar component not on a day... I am fighting with that for a week and still doesn't find any solution for that, Most important for me is how to pass information that I want to render

<Hours/>
Component when I click on
<Day/>
component which is inside
<Calendar/>
Component.

Main Component

class Order extends Component {

constructor() {
super();

this.state = {
clicked: false,
clickedOption: false,
clickedCalendar: false,
clickedHours: false,
};

this.nameClick = this.nameClick.bind(this);

}



showCategory() {
this.setState({
clickedOption: !this.state.clickedOption
})
}

nameClick() {

this.setState({
clicked: !this.state.clicked
})
}

showHours() {
this.setState({
clickedHours: !this.state.clickedHours
})
}


render() {
return (
<div>
<TimeCalendar/>
<Employee onClick={() => this.showCategory()}/>
{this.state.clickedOption && <Categories onClick={() => this.nameClick()}/>}
{this.state.clicked && <Calendar onClick={() => this.showHours()}/>}
{this.state.clickedHours && <Hours/>}
</div>
)
}
}


Calendar Component

class Calendar extends Component {
constructor(props) {
super(props);

this.state = {
disabled: false,
month: moment(),
selected: moment().startOf('day')
};

this.previous = this.previous.bind(this);

this.next = this.next.bind(this);
}

previous() {
const {
month,
} = this.state;

this.setState({
month: month.subtract(1, 'month')
});

}

next() {
const {
month,
} = this.state;

this.setState({
month: month.add(1, 'month'),
})
}

select(day) {
this.setState({
selected: day.date,
month: day.date.clone(),
});
}

renderWeeks() {
let weeks = [];
let done = false;
let date = this.state.month.clone().startOf('month').add("w" - 1).day('Sunday');
let count = 0;
let monthIndex = date.month();

const {
selected,
month,
} = this.state;

while (!done) {
weeks.push(
<Week
key={date}
date={date.clone()}
month={month}
select={(day) => this.select(day)}
selected={selected}
/>
);
date.add(1, 'w');

done = count++ > 2 && monthIndex !== date.month();
monthIndex = date.month();
}
return weeks;
}

renderMonthLabel() {
const {
month
} = this.state;
return <span className="month-label">{month.format("MMMM YYYY")}</span>;
}

previousMonth() {
let lastMonth = this.state.month.subtract('month', 1).calendar();

if (lastMonth === true) {
this.state.disabled = true
} else {
this.state.disabled = false
}
}


render() {
return (
<div className="col-xs-4">
<section className="calendar" {...this.props}>
<header className="header">
<div className="month-display row">
<i className="arrow fa fa-angle-left" /*disabled={this.previousMonth()}*/
onClick={this.previous}/>
{this.renderMonthLabel()}
<i className="arrow fa fa-angle-right" onClick={this.next}/>
</div>
<DayNames/>
</header>
{this.renderWeeks()}
</section>
</div>
)
}
}


Week and Day Component

class Week extends Component {
constructor(props) {
super(props);
this.state = {
showHours: false
}

}

showHours() {
this.setState({
showHours: true
})
}

render() {
let days = [];
let {
date,
} = this.props;

const {
month,
selected,
select,
} = this.props;

for (let i = 0; i < 7; i++) {
let day = {
name: date.format('dd').substring(0, 1),
number: date.date(),
isCurrentMonth: date.month() === month.month(),
isToday: date.isSame(new Date(), 'day'),
date: date
};
days.push(
<Day
day={day}
selected={selected}
select={select}
key={day.num}
/>
)
;
date = date.clone();
date.add(1, 'day');
}
return (
<div className="row week" key={days[0]}>
{days}
</div>
)
}
}

class Day extends Component {
render() {
const {
day,
day: {
date,
isCurrentMonth,
isToday,
number
},
select,
selected
} = this.props;

return (
<span
key={date.toString()}
className={"day" + (isToday ? " today" : "") + (isCurrentMonth ? "" : " different-month") + (date.isSame(selected) ? " selected" : "")}
onClick={() => {select(day)}}>
{number}
</span>
)
}
}


Hour Component

class Hours extends Component {
constructor(props) {
super(props)
}


render() {
const marginStyle = {
marginTop: "10px"
};


return (
<div {...this.props} className="block-hours col-xs-4">
<form action="">
<span className="block-hours hour-element">
8:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
8:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
9:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
9:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
10:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
10:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
11:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
11:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
12:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
12:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
13:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
13:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
14:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
14:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
15:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
15:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
16:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
16:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
17:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
17:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
18:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
18:30
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
19:00
<input type="radio" name="hours"/>
</span>
<span className="block-hours hour-element">
19:30
<input type="radio" name="hours"/>
</span>
<br/>
<div style={marginStyle}></div>
<button className="btn btn-primary btn-custom-color">Zapisz siÄ™ na wizytÄ™</button>
</form>
</div>
)
}
}

Answer Source

You call onClick when calendar is clicked, but you should to pass this func as prop:

{this.state.clicked && <Calendar showHours={this.showHours}/>}

And in caledar just call this function when day is clicked:

select(day) {
    this.setState({
        selected: day.date,
        month: day.date.clone(),
    });
    this.props.showHours();
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download