This the code:
import React, { Component } from 'react';
import { Select } from 'antd';
import { connect } from "react-redux";
class SelecionarCrypto extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onSearch = this.onSearch.bind(this);
console.log(this.props);
this.state = {
ValorState: "nada"
}
};
onChange(value) {
console.log(`selected ${value}`);
this.setState({ValorState: value});
console.log("New value onchange", this.ValorState)
}
onBlur() {
console.log('blur');
}
onFocus() {
console.log('focus');
}
onSearch(val) {
console.log('search:', val);
}
render(){
const { Option } = Select;
console.log("New value Render", this.ValorState)
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Seleciona:"
optionFilterProp="children"
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="ETH">ETH</Option>
<Option value="BTC">BTC</Option>
<Option value="XRP">XRP</Option>
</Select>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(SelecionarCrypto);
I am trying to change the value of ValorSate when onChange is done.
The error I am obtaining is: TypeError: this.setState is not a function.
I don´t find out the solution even readin about setSate() . I am followinf the same pattern of how-to´s or documentation but I no understanding something.
Now "New value onChange" or "New value Render" is always undefined"
console log:
Thank you.
I have modified your code. Please check it and try.
import React, { Component } from 'react';
import { Select } from 'antd';
import { connect } from "react-redux";
class SelecionarCrypto extends Component {
constructor(props) {
super(props);
console.log(this.props);
this.state = {
ValorState: 'nada'
}
};
onChange = (value) => {
console.log(`selected ${value}`);
this.setState({ValorState: 'algo'})
}
onBlur = () => {
console.log('blur');
}
onFocus = () => {
console.log('focus');
}
onSearch = (val) => {
console.log('search:', val);
}
render(){
const { Option } = Select;
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Seleciona:"
optionFilterProp="children"
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="ETH">ETH</Option>
<Option value="BTC">BTC</Option>
<Option value="XRP">XRP</Option>
</Select>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(SelecionarCrypto);
Move those functions outside the render, bind them to the this of your component and reference them with the this keyword:
class SelecionarCrypto extends Component {
constructor(props) {
...
this.onChange = this.onChange.bind(this)
// Similar for the rest
}
onChange(value) { this.setState({ ValorState: value }) }
onBlur() {}
onFocus() {}
onSearch() {}
...
render(){
...
return
(
<Select
showSearch
style={{ width: 200 }}
placeholder="Seleciona:"
optionFilterProp="children"
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="ETH">ETH</Option>
<Option value="BTC">BTC</Option>
<Option value="XRP">XRP</Option>
</Select>
)
}
import React, { Component } from 'react';
import { Select } from 'antd';
import { connect } from "react-redux";
class SelecionarCrypto extends Component {
constructor(props) {
super(props);
//this.onChange = this.onChange.bind(this);
console.log(this.props);
this.state = {
ValorState: 'nada'
}
};
onChange=(value)=> {
console.log(`selected ${value}`);
this.setState({ValorState: 'algo'})
}
function onBlur() {
console.log('blur');
}
function onFocus() {
console.log('focus');
}
function onSearch(val) {
console.log('search:', val);
}
render(){
const { Option } = Select;
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Seleciona:"
optionFilterProp="children"
onChange={this.onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="ETH">ETH</Option>
<Option value="BTC">BTC</Option>
<Option value="XRP">XRP</Option>
</Select>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(SelecionarCrypto);
function must be a outside from render and bind onchange function otherwise setstate will not effective
import React from "react";
import { Select } from "antd";
import { connect } from "react-redux";
class SelecionarCrypto extends React.Component {
constructor(props) {
super(props);
//this.onChange = this.onChange.bind(this);
console.log(this.props);
this.state = {
ValorState: "nada",
};
}
onChange(value) {
console.log(`selected ${value}`);
this.setState({ ValorState: "algo" });
}
onBlur() {
console.log("blur");
}
onFocus() {
console.log("focus");
}
onSearch(val) {
console.log("search:", val);
}
render() {
const { Option } = Select;
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Seleciona:"
optionFilterProp="children"
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="ETH">ETH</Option>
<Option value="BTC">BTC</Option>
<Option value="XRP">XRP</Option>
</Select>
);
}
}
const mapStateToProps = (state) => {
return {
token: state.token,
};
};
export default connect(mapStateToProps)(SelecionarCrypto);
Related
I am newbie to react, redux-saga, I have a dropdown in page Display, when I select it move to respective component (eg. policy, score), In Component Pages, I have a button Add New, on clicking it will navigate to a page as mentioned in link url , which is a page having cancel button, on cancelling it returns to the Display.js but no dropdown selected,
I would like to keep the state articleMode, when navigating to a page and returning back to same page,
articleMode returns to state -1 instead of selected component Policy or Score
actions.js
export const updateArticleMode = data => {
console.log(data.body);
return {
type: CONSTANTS.UPDATE_ARTICLE_MODE,
data: data.body
};
};
queryReducer.js
import * as CONSTANTS from "../constants/constants";
const initialState = {
articleMode: ""
}
case CONSTANTS.UPDATE_ARTICLE_MODE: {
return {
...state,
articleMode: data.mode
};
}
export default queryReducer;
constants.js
export const UPDATE_ARTICLE_MODE = "UPDATE_ARTICLE_MODE";
Display.js
import React from "react";
import { connect } from "react-redux";
import Policy from "../policy";
import Score from "./../score";
import { updateArticleMode } from "../../../../actions/actions";
const articleMode = [
{ name: "Select", id: "-1" },
{ name: "Score", id: "Score" },
{ name: "Policy", id: "Policy" }
]
class Display extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
articleMode: "-1"
};
}
componentWillMount = () => {
this.setState({ articleMode: this.props.queryData.articleMode || "-1" });
};
_getComponent = () => {
const { articleMode } = this.state;
if (articleMode === "Policy") {
return <DisplayPolicy></DisplayPolicy>;
}
if (articleMode === "Score") {
return <DisplayScore></DisplayScore>;
}
}
render() {
return (
<React.Fragment>
<select name="example"
className="simpleSearchSelect1"
value={this.state.articleMode}
onChange={event => {
this.setState({ articleMode: event.target.value });
this.props.dispatch(
updateArticleMode({ body: { mode: event.target.value } })
);
}}
style={{ marginLeft: "2px" }}
>
{articleMode.length != 0 &&
articleMode.map((option, index) => {
const { name, id } = option;
return (
<option key={index} value={id}>
{name}
</option>
);
})}
</select>
{this.state.articleMode === "-1"
? this._renderNoData()
: this._getComponent()}
</React.Fragment>
)}
const mapStateToProps = state => {
return {
queryData: state.queryData
};
};
export default connect(mapStateToProps)(Display);
}
DisplayPolicy.js
import React from "react";
class DisplayPrivacyPolicy extends React.Component {
constructor(props) {
super(props);
}<Link
to={{
pathname: "/ui/privacy-policy/addNew",
state: {
language: "en"
}
}}
>
<button className="page-header-btn icon_btn display-inline">
<img
title="edit"
className="tableImage"
src={`${process.env.PUBLIC_URL}/assets/icons/ic_addstore.svg`}
/>
{`Add New`}
</button>
</Link>
AddNew.js
<Link
to =pathname: "/ui/display",
className="btn btn-themes btn-rounded btn-sec link-sec-btn"
>
Cancel
</Link>
I have below simple dropdown component
import React, { Fragment } from 'react';
export default class SimpleDropdown extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange = (event) => {
this.props.handleSelect(event);
}
render() {
return (
<Fragment>
<select className="dd-wrapper" onChange={this.handleChange}>
{this.props.list.map((item) => (
<option className="dd-list-item" key={item.name} value={item.name}>{item.name}</option>)
)}
</select>
</Fragment>
);
}
}
I'm using this component in some other place as below along with NewMeasureDialogue component.Now,When I select 'Base Measure' from the dropdown and clicked on NewMeasureDialogue 'onYesClicked'.The value from BaseMeasure should be changed to Calculated Measure.
export class ParentComponent {
constructor(props) {
super(props);
this.state = {
measures: [{
name: 'Calculated Measure',
},
{
name: 'Base Measure'
}
]
}
}
handleDropDownSelect = (event) => {
this.setState({
selectedValue: event.target.value,
isBaseMeasure: event.target.value === 'Base Measure' ? true : false
})
}
render() {
return (
<div>
<SimpleDropdown list={this.state.measures} handleSelect={this.handleDropDownSelect} />
<NewMeasureDialogue msg={StringConstants.NEW_MEASURE_DIALOGUE_TEXT} show={this.state.show} close={this.close} onYesClicked={this.onYesClicked} />
</div>
)
}
}
Can someone tell me how to change the dropdownvalue when onYesclicked is performed on NewMeasure Dialogue.
in order to achieve this, you may want to convert your SimpleDropdown into a fully controlled component, meaning it should accept not only handleSelect method, but also a value property
import React, { Fragment } from 'react';
export default class SimpleDropdown extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange = (event) => {
this.props.handleSelect(event);
}
render() {
return (
<Fragment>
<select className="dd-wrapper" value={this.props.value} onChange={this.handleChange}>
{this.props.list.map((item) => (
<option
className="dd-list-item"
key={item.name}
value={item.name}
>
{item.name}
</option>
))}
</select>
</Fragment>
);
}
}
and do some modification in ParentComponent
export class ParentComponent {
constructor(props) {
super(props);
this.state = {
selectedValue: '',
measures: [{
name: 'Calculated Measure',
},
{
name: 'Base Measure'
}
]
}
}
handleDropDownSelect = (event) => {
this.setState({
selectedValue: event.target.value,
isBaseMeasure: event.target.value === 'Base Measure' ? true : false
})
}
onYesClicked = () => {
this.setState({selectedValue: 'Calculated Measure'})
}
render() {
return (
<div>
<SimpleDropdown
list={this.state.measures}
handleSelect={this.handleDropDownSelect}
value={this.state.selectedValue}
/>
<NewMeasureDialogue
msg={StringConstants.NEW_MEASURE_DIALOGUE_TEXT}
show={this.state.show}
close={this.close}
onYesClicked={this.onYesClicked}
/>
</div>
)
}
}
I have a component which renders Input type='select': (I am using reactstrap)
import React, {Component} from 'react'
import {
Form,
FormGroup,
Input,
Button,
Col,
} from 'reactstrap'
import {
withRouter,
} from 'react-router'
import Context from '../../../../../provider'
class NewPost extends Component {
constructor(props) {
super(props)
this.state = {
subreddits: [],
subreddit_selected: '',
subreddit_id: 0,
...
}
this.handleSubredditSelect = this.handleSubredditSelect.bind(this)
}
componentDidMount() {
fetch('/api/reddit/r/')
.then(data => data.json())
.then(json => {
this.setState({
subreddits: json,
...
})
})
}
handleSubredditSelect(event) {
console.log('selected id: ',event.target.id)
this.setState({
subreddit_selected: event.target.value,
subreddit_id: event.target.id,
}, () =>
this.props.history.push(`/${this.state.subreddit_selected}/new/`)
)
}
...
render() {
return (
<Context.Consumer>
{context => {
return (
<React.Fragment>
<Form
...
>
<FormGroup row>
<Col sm={7}>
<Input
type="select"
onChange={this.handleSubredditSelect}
required
>
<option key='0' disabled selected>Select an Option</option>
{this.state.subreddits.map((subreddit) => {
return (
<option key={subreddit.id} id={subreddit.id}>{'r/' + subreddit.name}</option>
)
})}
</Input>
</Col>
</FormGroup>
...
</React.Fragment>
)
}}
</Context.Consumer>
)
}
}
export default withRouter(NewPost)
So, I have a function handleSubredditSelect which does the following:
handleSubredditSelect(event) {
this.setState({
subreddit_selected: event.target.value,
subreddit_id: event.target.id,
}, () =>
this.props.history.push(`/${this.state.subreddit_selected}/new/`)
)
}
In this function I am not getting any value for event.target.id.
I have tried event.target.key as well but that returned an empty string "".
I want to set subreddit_id in state to the selected option's ID
The selecting does not work because event.target in <select> element returns entire tree with options:
// result of event.target:
<select>
<option id="id-1" value="some1">some1</option>
<option id="id-2" value="some2">some2</option>
<option id="id-3" value="some3">some3</option>
</select>
Instead the selected one.
For accessing the current option element from select you should rely on selectedIndex:
event.target[event.target.selectedIndex].id
The code:
export default class SelectForm extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "some1",
id: "id-1"
};
}
handleChange = event => {
console.log("event", event.target, event.target.selectedIndex);
this.setState({
value: event.target.value,
id: event.target[event.target.selectedIndex].id
});
};
render() {
return (
<div>
<select value={this.state.sex} onChange={this.handleChange}>
<option id="id-1" value="some1">some1</option>
<option id="id-2" value="some2">some2</option>
<option id="id-3" value="some3">some3</option>
</select>
ID: {this.state.id}
</div>
);
}
}
You can use selectedIndex attribute of select:
handleSubredditSelect(event) {
const selectedOption = event.target.childNodes[event.target.selectedIndex];
this.setState({
subreddit_selected: event.target.value,
subreddit_id: selectedOption.id,
}, () =>
this.props.history.push(`/${this.state.subreddit_selected}/new/`)
)
}
Here is the sandbox: https://codesandbox.io/s/n5679m5owj
AFAIK event.target.id should be working, doing the same in my project.
But should't it be
<Input
type="select"
onChange={(e) => this.handleSubredditSelect}
required>`
? (No parantheses after the methodname)
i'm pretty new to react and redux and i'm having an issue here. It's mandatory to use only stateless components with containers whenever state handing is required. These two components are:
import React from 'react';
import DatePicker from '../DatePicker';
class DayInput extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
dateValue: new Date(),
activeDateWidget: false,
};
}
changeDate(date) {
this.setState({
dateValue: date,
});
}
changeActiveDateWidget(e) {
e.stopPropagation();
this.setState({
activeDateWidget: !this.state.activeDateWidget,
});
}
render() {
const { input, meta } = this.props;
const { dateValue, activeDateWidget } = this.state;
return (
<div>
<input
{...input}
className="form-control"
type="text"
value={dateValue}
onClick={this.changeActiveDateWidget}
// onBlur={this.changeActiveDateWidget}
/>
{activeDateWidget ? (
<div>
<DatePicker
changeActiveDateWidget={this.changeActiveDateWidget}
changeDate={this.changeDate}
dateValue={dateValue}
/>
</div>
) : (
<div />
)}
</div>
);
}
}
export default DayInput;
import React from 'react';
import 'react-day-picker/lib/style.css';
import DayPicker, { DateUtils } from 'react-day-picker';
class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
selectedDay: new Date(),
};
}
componentDidMount() {
if (this.input) {
this.input.focus();
}
}
handleDayClick(e, day, { disabled }) {
e.stopPropagation();
if (disabled) {
return;
}
this.setState({ selectedDay: day }, () => {
this.props.changeDate(day);
this.props.changeActiveDateWidget();
});
}
focusThisComponent(e) {
if (e) {
this.input = e;
}
}
render() {
const { changeActiveDateWidget } = this.props;
const { selectedDay } = this.state;
return (
<div
ref={this.focusThisComponent}
tabIndex="1"
>
<DayPicker
id="THISTHING"
initialMonth={selectedDay}
selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
onDayClick={this.handleDayClick}
/>
</div>
);
}
}
export default DatePicker;
As you can see the first component is wrapped inside the second component. I tried to convert the first component myself like this:
const DayInput = props => {
<input
{...props.input}
type="text"
value= {new Date()}
onClick={()=>??}
/>
}
but as you can see i dont know how to handle the onclick event. Can someone help me to achieve this?
To turn your component in a stateless component, you must pass everything as properties of the component.
This will be your DayInput splitted into 2 components :
const DayInputShow = props => {
return (<input
{...props.input}
type="text"
value= {props.value}
onClick={(event)=>props.onClick()}
/>);
};
const DayInputEdit = props => {
return (<DatePicker
changeActiveDateWidget={props.changeActiveDateWidget}
changeDate={props.onChange}
dateValue={props.value}
/>);
};
DayInputShow.propTypes = {
value: PropTypes.date,
onClick: PropTypes.func,
}
DayInputEdit.propTypes = {
value: PropTypes.date,
onChange: PropTypes.func,
}
And this will be the root component (uncomplete and still statefull) :
class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
selectedDay: new Date(),
};
}
componentDidMount() {
if (this.input) {
this.input.focus();
}
}
handleDayClick(e, day, { disabled }) {
e.stopPropagation();
if (disabled) {
return;
}
this.setState({ selectedDay: day }, () => {
this.props.changeDate(day);
this.props.changeActiveDateWidget();
});
}
focusThisComponent(e) {
if (e) {
this.input = e;
}
}
render() {
const { changeActiveDateWidget } = this.props;
const { selectedDay } = this.state;
let dayPicker;
if (this.input) {
dayPicker = <DayPickerEdit
value={this.state.selectedDay}
onChange={(value) => {this.setState({selectedDay: value})}}
selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
onDayClick={this.handleDayClick}
/>
} else {
dayPicker = <DayPickerShow
value={this.state.selectedDay}
ref={(input) => { this.inputRef = input; }} />
onClick={() => {this.focusThisComponent(this.inputRef )}}
/>
}
return (
<div
ref={this.focusThisComponent}
tabIndex="1"
>
{dayPicker }
</div>
);
}
}
export default DatePicker;
My onChange() function does not run unless I use jQuery for some reason. The reason why I have to add the onChange listener in componentDidMount() is because I'm using MaterializeCSS which transforms your select tag into a ul. The code below works fine:
onChange(e) {
let inspectionTime = e.target.value;
this.setState({ inspectionTime });
}
componentDidMount() {
let $inspectionDropdown = $(ReactDOM.findDOMNode(this.refs.inspection));
$inspectionDropdown.on('change', this.onChange);
}
but this code does not:
onChange(e) {
let inspectionTime = e.target.value;
this.setState({ inspectionTime });
}
componentDidMount() {
let inspectionDropdown = ReactDOM.findDOMNode(this.refs.inspection);
inspectionDropdown.addEventListener('change', this.onChange);
}
Here is the code for the whole component if it helps at all:
import React from 'react';
import ReactDOM from 'react-dom';
class InspectionMode extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.defaultValue = 'selected';
this.state = { inspectionTime: 0 };
}
onChange(e) {
let inspectionTime = e.target.value;
this.setState({ inspectionTime });
}
componentDidMount() {
let inspectionDropdown = ReactDOM.findDOMNode(this.refs.inspection);
inspectionDropdown.addEventListener('change', this.onChange);
}
render() {
let classes = 'input-field col s10 offset-s1 l3';
return (
<div className={classes}>
<select onChange={this.onChange} ref="inspection" value={this.state.inspectionTime}>
<option value="0">None</option>
<option value='5'>5 Seconds</option>
<option value='10'>10 Seconds</option>
<option value='15'>15 Seconds</option>
</select>
<label>Inspection Time</label>
</div>
);
}
}
export default InspectionMode;
The problem is that the plugin is emitting a custom change event. React's event system doesn't recognize custom events (not sure why).
In this case a manual change listener is the right solution. The way you improve this is by abstracting the select element to an 'atom'.
class Select extends React.Component {
static propTypes = {
value: React.PropTypes.string,
options: React.PropTypes.arrayOf(
React.PropTypes.shape({
text: React.PropTypes.string.isRequired,
value: React.PropTypes.string.isRequired,
})
).isRequired
};
constructor() {
super();
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.props.onChange(e.target.value);
}
componentDidMount() {
let select = this.refs.select;
select.addEventListener('change', this.onChange, false);
}
componentWillUnmount(){
let select = this.refs.select;
select.removeEventListener('change', this.onChange, false);
}
render() {
let classes = 'input-field col s10 offset-s1 l3';
return (
<div className={classes}>
<select ref="select" value={this.props.value}>
{this.props.options.map((x) => {
return <option key={x.value} value={x.value}>{x.text}</option>;
})}
</select>
</div>
);
}
}
You can then use this in InspectionMode or anywhere else in your UI.
class InspectionMode extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.value = 'selected';
this.state = { inspectionTime: 0 };
}
onChange(inspectionTime) {
this.setState({ inspectionTime });
}
render() {
return (
<div>
<Select
value={this.state.inspectionTime}
onChange={this.onChange}
options={[
{value: '0', text: 'None'},
{value: '5', text: '5 seconds'},
{value: '10', text: '10 seconds'},
{value: '15', text: '15 seconds'},
]}
/>
<label>Inspection Time</label>
</div>
);
}
}