I have one main component as follows :
render() {
const language = this.props.language.default.portal;
return (
<div>
<div className="searchLeft noPadding col-xl-2 col-lg-2 col-md-2 col-sm-3 col-xs-5">
<Price language={language} actionFilters={this.props.actionFilters} allCarsInTheList={this.props.carsToShow}/>
</div>
<div className="contentRight noPadding col-xl-10 col-lg-10 col-md-10 col-sm-9 col-xs-7">
<div className="filterBar">
<SmallFilters language={language} filters={this.props.filters} allCarsInTheList={this.props.carsToShow} actionFilters={this.props.actionFilters}/>
</div>
</div>
</div>
);
}
My price component is as follows :
export default class PriceRangeFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
range: {
low: _.min(this.props.allCarsInTheList.map (i => i.price)),
high: _.max(this.props.allCarsInTheList.map (i => i.price)),
active: false
}
};
}
handleFilter(){
if(this.state.range.active){
this.props.actionFilters.addPriceRangeFilter(this.state.range);
}else{
this.props.actionFilters.removePriceRangeFilter();
}
}
changeFilter(range) {
this.setState({range: range}, this.handleFilter);
}
deActivate(event) {
event.preventDefault();
let n_range = this.state.range;
n_range.active = false;
this.changeFilter(n_range);
}
renderSmall() {
return (
<div key={this.props.key} className="filter">
{this.props.title} <Link to="" onClick={this.deActivate.bind(this)}><FontAwesome name="times" className="portalFaRedIcon"/></Link>
</div>
);
}
render(){
const language = this.props.language;
if(this.props.recap) return this.renderSmall();
console.log(this.state.range);
return (
<div>
<div className="priceTitle">{language.price}</div>
<SliderRange language={language}
range={this.state.range}
min={_.min(this.props.allCarsInTheList.map (i => i.price))}
max={_.max(this.props.allCarsInTheList.map (i => i.price))}
step={data.configuration.PRICE_RANGE_STEP}
sign="€"
type="price"
onChange={this.changeFilter.bind(this)} />
</div>
);
}
}
And my SmallFilters component is as follows :
import PriceFilter from './price';
class filters extends React.Component {
checkFilter(name, filters){
return filters.some(f => name == f.name);
}
showFilter(filters){
if(this.checkFilter(filter_names.priceRange, filters)){
return <PriceFilter recap={this.checkFilter(filter_names.priceRange, filters)} title="Price" allCarsInTheList={this.props.allCarsInTheList} actionFilters={this.props.actionFilters}/>
}
}
render(){
const language = this.props.language;
const filters = this.props.filters;
return (
<div className="filters noPadding col-xl-8 col-lg-6 col-md-6 col-sm-5 col-xs-12">
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={500}>
{this.showFilter(filters)}
</ReactCSSTransitionGroup>
</div>
);
}
}
The problem is in the SmallFilters component. I include there the same Price component as in the Search component. Then, in the price component I return renderSmall function if this.props.recap is true.
When I click on the link inside renderSmall to deactivate the filter it should update the state. But the state isn't changed. this.state.range.active stays true.
Any advice?
UPDATE
SliderRange component code is as follows :
import React, {PropTypes} from 'react';
import {formatNumber} from './formatNumber';
export default class SliderRange extends React.Component {
constructor(props) {
super(props);
this.state = this.getStateFromProps(this.props);
}
componentWillReceiveProps(newProps){
this.setState(this.getStateFromProps(newProps));
}
getStateFromProps(props) {
return {
low: props.range.low,
high: props.range.high,
active: props.range.active
};
}
numberWithSpace(number) {
return (this.props.type == "year") ? number : formatNumber(number);
}
handleChange(low, high, active) {
let n_active = active;
if(low!=this.state.low) n_active = true;
if(high!=this.state.high) n_active = true;
if(low == this.props.min && high == this.props.max) n_active = false;
const result = {
low: low,
high: high,
active: n_active
};
this.props.onChange(result);
}
handleActive(event) {
const checkbox = event.target.checked;
let low = this.state.low;
let high = this.state.high;
if(checkbox && this.state.low == this.props.min && this.state.high == this.props.max) {
low = this.props.min + this.props.step;
high = this.props.max - this.props.step;
}else{
low = this.props.min;
high = this.props.max;
}
this.handleChange(low, high, checkbox);
}
handleLow(event) {
if(parseInt(event.target.value) < parseInt(this.state.high)){
this.handleChange(event.target.value, this.state.high, this.state.active);
}
}
handleHigh(event) {
if(parseInt(event.target.value) > parseInt(this.state.low)) {
this.handleChange(this.state.low, event.target.value, this.state.active);
}
}
render() {
const sign = this.props.sign;
const min = this.props.min;
const max = this.props.max;
const step = this.props.step;
const low = this.state.low;
const high = this.state.high;
const active = this.state.active;
return (
<div>
<div className="rangeValues">Range : {this.numberWithSpace(low)} {sign} - {this.numberWithSpace(high)} {sign}</div>
<section className="range-slider">
<input type="checkbox" checked={active} onChange={this.handleActive.bind(this)}/>
<input type="range" name="first" value={low} min={min} max={max} step={step} onChange={this.handleLow.bind(this)} className="firstRange"/>
<input type="range" name="second" value={high} min={min} max={max} step={step} onChange={this.handleHigh.bind(this)} className="secondRange"/>
<div className="minValue">{this.numberWithSpace(min)} {sign}</div>
<div className="maxValue">{this.numberWithSpace(max)} {sign}</div>
</section>
</div>
);
}
}
SliderRange.propTypes = {
language: PropTypes.object.isRequired,
range: PropTypes.object.isRequired,
min: PropTypes.number.isRequired,
max: PropTypes.number.isRequired,
step: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired
};
You are changing a nested property. Try creating a new object using Object.assign() as follows:
deActivate(event) {
event.preventDefault();
let n_range = Object.assign({}, this.state.range);
n_range.active = false;
this.changeFilter(n_range);
}
Related
I am writing todo app. There are main files in my directory now:
App (rendering main page with header and buttons)
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { triggerText: 'Create a task' };
}
propTypes = {
triggerText: PropTypes.string.isRequired,
handleSubmit: PropTypes.object.isRequired,
};
render() {
const { triggerText } = this.state;
const { handleSubmit } = this.props;
return (
<div className="App">
<header className="App-header">
<h1>To Do List</h1>
<div id="tasksList">
<span className="tasks active">Tasks</span>
</div>
<div id="categoriesList">
<span className="categories">Categories</span>
</div>
<div>
<Container triggerText={triggerText} onSubmit={handleSubmit} /> // creates modal dialog and uses TodoForm
</div>
</header>
<div id="container" className="container">
<TodoBox tasks={[]}/>
</div>
</div>
);
}
}
TodoForm (create a form)
export default class TodoForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: '', tasks: [] };
}
propTypes = {
handleSubmit: PropTypes.object.isRequired,
}
handleRemove = (currentTaskId) => (e) => {
e.preventDefault();
const { tasks } = this.state;
this.setState({ tasks: tasks.filter(({ id }) => id !== currentTaskId) });
};
handleChange = (e) => {
e.preventDefault();
this.setState({ value: e.target.value });
}
handleSubmit = (e) => {
e.preventDefault();
const { value, tasks } = this.state;
const newTask = { id: uniqueId(), text: value };
this.setState({ value: '', tasks: [newTask, ...tasks] });
}
render() {
const { value } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="text"><strong>Create a task</strong></label>
<input
type="text"
onChange={this.handleChange}
value={value}
required
className="form-control"
id="text"
placeholder="I am going..."
/>
</div>
<div className="form-group">
<button type="submit" className="form-control btn btn-primary">Add</button>
</div>
</form>
);
}
}
TodoBox (generating list of tasks)
class Item extends React.Component {
propTypes = {
onRemove: PropTypes.object.isRequired,
task: PropTypes.string.isRequired,
};
render() {
const { task, onRemove } = this.props;
return (
<div className="row">
<div>
<button type="button" className="btn btn-primary" onClick={onRemove}>-</button>
</div>
<div className="col-10">{task.text}</div>
</div>
);
}
}
export default class TodoBox extends React.Component {
constructor(props) {
super(props);
}
propTypes = {
tasks: PropTypes.string.isRequired,
}
render() {
const { tasks } = this.props;
return (
<div className="item">
{tasks.map((task) => (
<div key={task.id}>
<Item task={task} onRemove={this.handleRemove} />
<hr />
</div>
))}
</div>
);
}
}
And the question is: how I can pass the state from TodoForm to TodoBox in App (it is initialize as an empty array now). I want to output tasks at the bottom of the same page in container after header element.
You can create a function (addTodo) in App component and pass it down to the TodoForm component. In TodoForm component you can invoke the addTodo function from props and send the todoValue as arguments props.addTodo(todoValue). In addTodo function in App component you can update the todoValue to state. Once you update the state it will re-render the App component, then the TodoBox component will call with the updated todoValue value.
Note: But it is not best practice. The best practice is to use React Context
Making a CV creator and I've added a popup form for users to input data and then render to the page. I'm having a lot of trouble figuring out how to reopen the popup with already submitted data for editing however, been hours of googling and no closer to having any idea what to do
the main work code
import React, { Component } from "react";
import Popup from 'reactjs-popup';
import CreateItems from './CreateItems'
class Work extends Component {
constructor(props) {
super(props);
this.state = {
items: []
};
this.addItem = this.addItem.bind(this);
this.deleteItem = this.deleteItem.bind(this);
}
addItem(e) {
var newItem = {
title: this.title.value,
company: this.company.value,
location: this.location.value,
date: this.date.value,
description: this.description.value,
key: Date.now()
};
this.setState((prevState) => {
return {
items: prevState.items.concat(newItem)
};
});
this.title.value = "";
this.company.value = "";
this.location.value = "";
this.date.value = "";
this.description.value = "";
e.preventDefault();
}
deleteItem(key) {
var filteredItems = this.state.items.filter(function (item) {
return (item.key !== key);
});
this.setState({
items: filteredItems
});
}
render(){
return (
<div id = "work-container">
<h2>Experience:</h2>
<CreateItems entries = {this.state.items}
delete= {this.deleteItem}/>
<Popup trigger={<button> Add New</button>} modal nested>
{close => (
<form id = 'modal-container' onSubmit={this.addItem}>
<span id = 'modal-header'>Add work experience</span>
<div id = 'row'>
<div className = 'row-segment-left'>
<label htmlFor = "job-title">Job Title</label>
<input id = "job-title" type = "text" ref={(a) => this.title = a}></input>
</div>
<div className = "row-segment-right">
<label htmlFor ='job-company'>Company</label>
<input id = 'job-company' type= 'text' ref={(a) => this.company = a}></input>
</div>
</div>
<div id = 'row'>
<div className = 'row-segment-left'>
<label htmlFor = "job-location">Job Location</label>
<input id = "job-location" type = "text" ref={(a) => this.location = a}></input>
</div>
<div className = "row-segment-right">
<label htmlFor ='job-date'>Date of Employment</label>
<input id = 'job-date' type= 'text' ref={(a) => this.date = a}></input>
</div>
</div>
<div id ='bottom-row'>
<label htmlFor ='job-description'>Job Description</label>
<textarea id = 'job-description' rows = '5' placeholder = 'Describe your duties...'
ref={(a) => this.description = a}></textarea>
</div>
<div id = 'button-container'>
<button type = "submit" >Submit</button>
<button onClick={() => {
close();
}}>Cancel</button>
</div>
</form>
)}
</Popup>
</div>
)}};
export default Work;
The code for creating and adding the content
import React, { Component } from "react";
class CreateItems extends Component {
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);
}
delete(key) {
this.props.delete(key);
}
createTasks(item) {
return <div className = 'work-segment' key={item.key}>
<h3>{item.title}</h3>
<span>{item.company} / {item.location} / {item.date}</span>
<p>{item.description}</p>
<span>
<button>Edit</button>
<button onClick={() => this.delete(item.key)}>Delete</button>
</span>
</div>
}
render() {
var workEntries = this.props.entries;
var workItems = workEntries.map(this.createTasks);
return (
<div id = 'work-items'>
{workItems}
</div>
);
}
};
export default CreateItems;
I'm trying to pass data from a React form in a Child component to a Parent component, but i'm missing something.
When i pass the data from within the parent component only, everything works fine. However i would really like to learn how to use several components.
I'm new to React and i would really appreciate help from someone.
This is my Parent Component:
import React from 'react';
import CalculateIMC from './calculateIMC'
import Results from './results';
import '../css/Form.css';
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
name: "",
height: "",
weight: "",
bmi: "",
};
this.calBmi = this.calBmi.bind(this);
}
calBmi = () => {
const { height, weight } = this.state;
const calcBmi = (weight / (height / 100) ** 2).toFixed(2);
const bmiClass = this.getBmi(calcBmi);
this.setState({isSubmitted: true})
this.setState({
bmi: calcBmi,
bmiClass : bmiClass
})
}
getBmi = (bmi) => {
if(bmi < 18.5) {
return "Underweight";
}
if(bmi >= 18.5 && bmi < 24.9) {
return "Normal weight";
}
if(bmi >= 25 && bmi < 29.9) {
return "Overweight";
}
if(bmi >= 30) {
return "Obesity";
}
}
clearAll = () => {
console.log("test");
this.setState({
name: "",
height: "",
weight: "",
bmi: ""
});
};
render() {
return (
<div className="App">
<CalculateIMC calBmi={this.calBmi}/>
{this.state.isSubmitted && <Results {...this.state}/>}
</div>
);
}
}
export default App
Child component
import React from 'react';
class CalculateIMC extends React.Component{
constructor(props) {
super(props)
this.state = {
name: "",
height: "",
weight: "",
bmi: "",
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = (e) => {
e.preventDefault()
this.props.calBmi()
}
render() {
return (
<div className="container">
<form className="card-body" onSubmit={e => this.handleSubmit(e)}>
<div className="field">
<div className="two fields">
<div className="field">
<label>Nom : </label>
<input type="text" required placeholder="Saisir votre nom" value={this.state.name} onChange={e => this.setState({ name: e.target.value })}/>
</div>
<div className="field">
<label>Taille : </label>
<input type="number" required placeholder="Taille en cms" value={this.state.height} onChange={e => this.setState({ height: e.target.value })}/>
</div>
<br />
<div className="field">
<label>Poids : </label>
<input type="number" required placeholder="Poids en Kgs" value={this.state.weight} onChange={e => this.setState({ weight: e.target.value })}/>
</div>
</div>
<button type="submit" className="ui button" tabIndex="1">Calcul</button>
<button className="ui button" tabIndex="0" onClick={this.props.clearAll}>Effacer</button>
</div>
</form>
</div>
)
}
}
export default CalculateIMC
You are not passing the child's form data to the parent, instead you are just calling the callback without parameters, that's the problem.
On the child component you should do this (or similar):
handleSubmit = (e) => {
e.preventDefault();
this.props.calBmi(this.state);
}
On the parent:
calBmi = (childFormData) => {
const { height, weight } = childFormData;
const calcBmi = (weight / (height / 100) ** 2).toFixed(2);
const bmiClass = this.getBmi(calcBmi);
this.setState({isSubmitted: true}); // you can merge this setState with below one
this.setState({
bmi: calcBmi,
bmiClass : bmiClass
})
}
You need to update your calBmi() prop to have the form values as a parameter:
parent:
calBmi = (formParameters) => {
// do something with formParameters
}
child:
handleSubmit = (e) => {
e.preventDefault()
this.props.calBmi({
name: this.state.name,
height: this.state.height,
weight: this.state.weight,
}
})
}
I suggest you also change its name calBmi => onFormSubmit
I have written the start of a todo list in reactjs and was looking to improve the functionality of how the todos are added to the state. Currently I am concat(ting) the value in put to an array which is in the state, then splicing off the selected li element. It seems to be a bit buggy when you add the first todo. Should i be using reacts immutability helpers to acheive this? Seems overkill to add another thing that can be acheived in plain js.
//Input component
const Input = props => {
return (
<div className="form-group">
<input
className="form-control"
value={props.value}
onChange={props.update}
type="text"
/>
<button className="btn btn-default" onClick={props.handleClick}>
Add Todo
</button>
</div>
);
};
//display list of todos
const Displaytodo = (props) => {
const todolist = props.todo;
const listItems = todolist.map((todo, index) =>
<li
className={
props.highlight ? 'list-unstyled todoItem highlight' : 'list-unstyled todoItem '
}
key={index}>
{todo}
<div
onClick={props.removeTodo.bind(this, index)}
className="removeTodo">
<i className="fa fa-trash" />
</div>
<div onClick={props.changeHighlight.bind(this,index)} className="checkTodo">
<i className="fa fa-check-circle" onClick={props.highlight} />
</div>
</li>
);
return <ul className="todos">{listItems}</ul>;
};
//controlled state component
class Layout extends React.Component {
constructor() {
super();
this.state = { text: "Hello", todo: [], highlight: false };
}
update(e) {
this.setState({ text: e.target.value });
}
handleClick() {
const text = this.state.text;
if (text.length > 0) {
this.setState(
{ todo: this.state.todo.concat(text), text: "", highlight: false },
function() {
console.log(this.state.todo);
}
);
} else {
alert("please enter something");
}
}
removeTodo(e) {
this.state.todo.splice(e, 1);
this.setState({ todo: this.state.todo });
}
changeHighlight(index, e) {
const highlight = this.state.highlight;
this.setState(prevState => ({
highlight: !prevState.highlight
}));
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-4 col-md-offset-4">
<div className="wrapper">
<h1>Todo List</h1>
<Input
value={this.state.text}
update={this.update.bind(this)}
handleClick={this.handleClick.bind(this)}
/>
<Displaytodo
removeTodo={this.removeTodo.bind(this)}
todo={this.state.todo}
changeHighlight={this.changeHighlight.bind(this)}
highlight={this.state.highlight}
/>
</div>
</div>
</div>
</div>
);
}
}
const app = document.getElementById("app");
ReactDOM.render(<Layout />, app);
https://codepen.io/mhal12/pen/MomWVg
Also when the user clicks the green tick, it will highlight the row by toggling class 'highlight' off and on, but in console it giving an error. which links to
https://facebook.github.io/react/docs/error-decoder.html?invariant=94&args[]=onClick&args[]=boolean
Simply remove the onClick on <i className="fa fa-check-circle" onClick={props.highlight} />.
As for the highlighting on each todo, it's a bit more complex. You have to have an id on each todo, and then pass the id to the changeHighlight function. You have to remove highlight from global state, and assign a highlight boolean on each todo. Then you have to display todos accordingly.
Same stuff for the removeTodo function, you pass in an id to remove it in the parent component.
Here's the full code :
const Input = props => {
return (
<div className="form-group">
<input
className="form-control"
value={props.value}
onChange={props.update}
type="text"
/>
<button className="btn btn-default" onClick={props.handleClick}>
Add Todo
</button>
</div>
);
};
const Displaytodo = (props) => {
const changeHighlight = function(id) {
props.changeHighlight(id);
}
const removeTodo = function(id) {
props.removeTodo(id);
}
const todolist = props.todo;
const listItems = todolist.map((todo, index) =>
<li
className={
todo.highlight ? 'list-unstyled todoItem highlight' : 'list-unstyled todoItem '
}
key={todo.id}>
{todo.text}
<div
onClick={removeTodo.bind(event, todo.id)}
className="removeTodo">
<i className="fa fa-trash" />
</div>
<div onClick={changeHighlight.bind(event, todo.id)} className="checkTodo">
<i className="fa fa-check-circle" />
</div>
</li>
);
return <ul className="todos">{listItems}</ul>;
};
class Layout extends React.Component {
constructor() {
super();
this.state = {text: "Hello", todo: []};
}
update(e) {
this.setState({ text: e.target.value });
}
handleClick() {
const text = this.state.text;
if (text.length > 0) {
this.setState(
{ todo: this.state.todo.concat({
id: this.state.todo.length + 1,
text: this.state.text,
highlight: false
}), text: ""},
function() {
console.log(this.state.todo);
}
);
} else {
alert("Please enter something");
}
}
removeTodo(id) {
let todos = this.state.todo;
for (let i = 0; i < todos.length; i++) {
let todo = todos[i];
if (todo.id == id) {
todos.splice(i, 1);
}
}
this.setState({ todo: todos });
}
changeHighlight(id) {
let todos = this.state.todo;
for (let i = 0; i < todos.length; i++) {
let todo = todos[i];
if (todo.id == id) {
todos[i].highlight = !todos[i].highlight;
}
}
this.setState({
todo : todos
});
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-4 col-md-offset-4">
<div className="wrapper">
<h1>Todo List</h1>
<Input
value={this.state.text}
update={this.update.bind(this)}
handleClick={this.handleClick.bind(this)}
/>
<Displaytodo
removeTodo={this.removeTodo.bind(this)}
todo={this.state.todo}
changeHighlight={this.changeHighlight.bind(this)}
/>
</div>
</div>
</div>
</div>
);
}
}
const app = document.getElementById("app");
ReactDOM.render(<Layout />, app);
I have one component (Fuel) which I use in two other components (Search and SmallFilters) :
Search component is as follows :
class search extends React.Component {
render() {
const language = this.props.language.default.portal;
return (
<div>
<div className="searchTitle"><FontAwesome name="search" className="portalFaIcon"/> {language.search}</div>
<Fuel language={language} actionFilters={this.props.actionFilters} filters={this.props.filters}/>
</div>
);
}
}
function mapStateToProps(state, ownProps){
return {
favorites: state.favorites,
filters: state.filters,
carsToShow: state.carsToShow
};
}
function mapDispatchToProps(dispatch){
return {
actionFilters: bindActionCreators(filterActions, dispatch),
actionCarsToShow: bindActionCreators(actionCarsToShow, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(search);
The SmallFilters is as follows :
render(){
return (
<div className="filters noPadding col-xl-8 col-lg-6 col-md-6 col-sm-5 col-xs-12">
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={500}>
<Fuel recap={true} title={_.startCase(_.toLower(filter_names.fuel))} {...this.props}/>
</ReactCSSTransitionGroup>
</div>
);
}
The Fuel component is as follows :
import React from 'react';
import FontAwesome from 'react-fontawesome';
import {Link} from 'react-router';
import { filter_names } from './filterActions';
export default class fuel extends React.Component {
constructor(props){
super(props);
this.state = this.getFilterValues()
}
emptyValues(){
return {
checkboxDiesel: false,
checkboxBenzine: false
}
}
handleFilter(){
if(this.state.checkboxDiesel || this.state.checkboxBenzine){
this.props.actionFilters.addFuelFilter(this.state);
}else{
this.props.actionFilters.removeFuelFilter();
}
}
handleDiesel(event){
const checkbox = event.target.checked;
this.setState({checkboxDiesel: checkbox, checkboxBenzine: this.state.checkboxBenzine}, () => this.handleFilter());
}
handleBenzine(event){
const checkbox = event.target.checked;
this.setState({checkboxBenzine: checkbox, checkboxDiesel: this.state.checkboxDiesel}, () => this.handleFilter());
}
deActivate(event) {
event.preventDefault();
this.setState(this.emptyValues(), () => this.handleFilter());
}
getFilterValues(){
debugger;
if(!this.props.filters.some(i => i.name === filter_names.fuel)){
return this.emptyValues();
}
return {
checkboxDiesel: this.props.filters.filter(f => f.name === filter_names.fuel).map(i => i.values.map(v => v.checkboxDiesel)),
checkboxBenzine: this.props.filters.filter(f => f.name === filter_names.fuel).map(i => i.values.map(v => v.checkboxBenzine))
};
/*let values = {};
this.props.filters.filter(f => {
if(f.name == filter_names.fuel){
values.checkboxDiesel = f.values[0].checkboxDiesel;
values.checkboxBenzine = f.values[0].checkboxBenzine;
}
});
return values;*/
}
renderSmall() {
let diesel = this.getFilterValues().checkboxDiesel ? "Diesel" : "";
let benzine = this.getFilterValues().checkboxBenzine ? "Benzine" : "";
return (
<div className="filter">
{this.props.title} <Link to="" onClick={this.deActivate.bind(this)}><FontAwesome name="times" className="portalFaRedIcon"/></Link>
<div className="filterValues">{diesel} {benzine}</div>
</div>
);
}
render() {
const language = this.props.language;
if(this.props.recap) return this.renderSmall();
console.log(this.props.filters);
return (
<div>
<div className="priceTitle" style={{padding: '5px 0'}}>{language.fuel}</div>
<div className="transmissionValues">
<input type="checkbox" onChange={this.handleDiesel.bind(this)} checked={this.getFilterValues().checkboxDiesel}/> <span>Diesel</span>
</div>
<div className="transmissionValues">
<input type="checkbox" onChange={this.handleBenzine.bind(this)} checked={this.getFilterValues().checkboxBenzine}/> <span>Benzine</span>
</div>
</div>
);
}
}
The problem is, when I click on one of those checkboxes, both are checked. And If I click on the same checkbox both are unchecked. But if I click on the other one nothing happends.
This.props.filters comes from redux store and it's something like this if one of those checkboxes is checked :
[{name: "FUEL", values: [{checkboxDiesel: true, checkboxBenzine: false}]}]
Any advice?
By a long shot, I think you should just use this.state to update your input's value. Read controlled components from the docs.
render() {
const language = this.props.language;
if(this.props.recap) return this.renderSmall();
console.log(this.props.filters);
return (
<div>
<div className="priceTitle" style={{padding: '5px 0'}}>{language.fuel}</div>
<div className="transmissionValues">
<input type="checkbox" onChange={this.handleDiesel.bind(this)} checked={this.state.checkboxDiesel}/> <span>Diesel</span>
</div>
<div className="transmissionValues">
<input type="checkbox" onChange={this.handleBenzine.bind(this)} checked={this.state.checkboxBenzine}/> <span>Benzine</span>
</div>
</div>
);
}
If there are any side-effects of this action, you can do that in handleDiesel or handleBenzine methods. Let me know if it works. Meanwhile, I'll try to understand more from your code.