React and setState and autocomplete - reactjs

Im using react and material ui.
This is my component
```
import React from 'react';
import lightBaseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import AutoComplete from 'material-ui/AutoComplete';
// the light theme
const lightMuiTheme = getMuiTheme(lightBaseTheme);
// the autocomplete component width
const Preferencestypeahead = {
maxWidth: 600,
position:'relative',
margin:'auto'
}
export default class Preferences extends React.Component {
constructor(props) {
super(props);
this.handleUpdateInput = this.handleUpdateInput.bind();
this.state = {
dataSource: [],
};
}
handleUpdateInput(value){
this.setState({
dataSource: [
value,
value + value,
value + value + value,
],
});
};
render() {
return (
<div>
<MuiThemeProvider muiTheme={lightMuiTheme}>
<section style={Preferencestypeahead}>
<AutoComplete
hintText="Type"
dataSource={this.state.dataSource}
onUpdateInput={this.handleUpdateInput.bind(this)}
floatingLabelText="Search"
fullWidth={true}
/>
</section>
</MuiThemeProvider>
</div>
)
}
}
I keep getting setState is not defined when I type anything inside the autocomplete. Where could I be going wrong? I have also faced this problem when I tried to import the tabs as well

You need to bind to "this"
This line is the problem:
this.handleUpdateInput = this.handleUpdateInput.bind();
Change it to:
this.handleUpdateInput = this.handleUpdateInput.bind(this);

Since you are already using ES6 you could just do
...
onUpdateInput={(val) => this.handleUpdateInput(val)}
...
then you don't need to do this --> this.handleUpdateInput = this.handleUpdateInput.bind(this); in your constructor

Related

Getting React component instance from ReactDOM.render() return

I have custom component Slider for Formio. Function attachReact() is attaching my custom component inside element provided by Formio. After attaching is done I am supposed to get an instance for that component from ReactDOM.render() returned right away but I am not. Later that instance is used by Formio to change field values which I need.
How can I make sure I get an instance from ReactDOM returned right away? I realise that feature will be removed in future from React but I still need it while Formio is using it.
import { ReactComponent } from "#formio/react";
import React from "react";
import ReactDOM from "react-dom";
import settingsForm from "./Slider.settingsForm";
class SliderCustomComp extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
};
}
setValue = (v) => {
this.setState({ value: v }, () => this.props.onChange(this.state.value));
};
render() {
return (
<div className="w-full" id="custcomp">
<input
className="w-full focus:outline-none"
type="range"
min={this.props.component.minRange}
max={this.props.component.maxRange}
value={this.state.value}
onChange={(e) => {
this.setValue(e.target.value);
}}
/>
<span>{this.state.value}</span>
</div>
);
}
}
export default class Slider extends ReactComponent {
constructor(component, options, data) {
super(component, options, data);
}
static schema() {
return ReactComponent.schema({
type: "sliderCustomComp",
label: "Default Label",
});
}
static editForm = settingsForm;
attachReact(element) {
console.log(element);
const instance = ReactDOM.render(
<SliderCustomComp
component={this.component} // These are the component settings if you want to use them to render the component.
value={this.dataValue} // The starting value of the component.
onChange={this.updateValue} // The onChange event to call when the value changes.}
/>,
element
);
console.log("instance in attachReact", instance);
return instance;
}
}
Use prop ref to get the instance:
const instanceRef = React.createRef();
ReactDOM.render(
<SliderCustomComp
ref={instanceRef}
component={this.component} // These are the component settings if you want to use them to render the component.
value={this.dataValue} // The starting value of the component.
onChange={this.updateValue} // The onChange event to call when the value changes.}
/>,
element
);
const instance = instanceRef.current;

React native set state is not working

I am trying to update state in react native component.
But its getting errors, Could someone help me.
I'm using react-native-cli verions: 2.0.1
react-native verions: 0.55.4
Here is my code:
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
state = {
isDone: false
};
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
onPress={this.onAction}
/>
</View>
)
}
}
export default ToggleButton;
You have three different solutions.
Bind your function in the constructor.
Use the experimental public class fields syntax.
Pass a lambda to executing your function.
The problem is that you're loosing the reference to this, because the function is not executed in the original context, so this.setState is not a function, but a undefined.
In this page there are examples for all of the approaches: https://reactjs.org/docs/handling-events.html
Change
onPress={this.onAction}
to
onPress={this.onAction.bind(this)}
Check: this
Below is the solution
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
// Add state in constructor like this
constructor(props){
super(props);
this.state = {
isDone: false
};
}
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
// Add function with onPress
onPress={() => this.onAction}
/>
</View>
)
}
}
export default ToggleButton;

React Draft.js toolbar plugin not showing

I've followed the docs on installing the inline and static toolbar plugins, but they seems to be nonexistent.
I'm using the Create React App CLI.
The component:
import React from 'react';
import {EditorState} from 'draft-js';
import Editor from 'draft-js-plugins-editor';
import createInlineToolbarPlugin from 'draft-js-inline-toolbar-plugin';
import createToolbarPlugin from 'draft-js-static-toolbar-plugin';
import 'draft-js/dist/Draft.css';
import 'draft-js-inline-toolbar-plugin/lib/plugin.css';
import 'draft-js-static-toolbar-plugin/lib/plugin.css';
const inlineToolbarPlugin = createInlineToolbarPlugin({
//I read somewhere that this plug-in needs this structure passed to it,
//but the example in the docs did not use it, and they are undefined anyway
// structure: [
// BoldButton,
// ItalicButton,
// UnderlineButton,
// CodeButton,
// Separator,
// ],
});
const toolbarPlugin = createToolbarPlugin();
class TextEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.onChange = (editorState) => this.setState({editorState});
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={[inlineToolbarPlugin, toolbarPlugin]}
/>
);
}
}
export default TextEditor;
That component is then passed to another component that just renders the editor and does nothing else.
I must be missing something, or not giving the plugins what they need, I just don't know what. I'm guessing the code I have is insufficient to start adding plugins in the first place?
You can define custom buttons to perform the desired operations like below:
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={[inlineToolbarPlugin, toolbarPlugin]}
/>
<button onClick={this._onBoldClick.bind(this)}>Bold</button> //add button to make bold
And now you can write a code to make bold in _onBoldClick method as follows:
_onBoldClick() {
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
}
You can take reference from the docs.
You need to import the buttons before you can create the toolbar
import {
ItalicButton,
BoldButton,
UnderlineButton,
CodeButton
} from "draft-js-buttons";
Also, you need to include the toolbar in your render function
const { Toolbar } = inlineToolbarPlugin;
render() {
return (
<div>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={[inlineToolbarPlugin, toolbarPlugin]}
/>
<Toolbar />
</div>
);

autocomplete is undefined with material-ui

I have the following code in a jsx file and I get error:
Uncaught ReferenceError: AutoComplete is not defined
From what I see it should be working ok, Code:
import React, {Component} from 'react';
import { Autocomplete } from 'material-ui';
class MaterialUIAutocomplete extends Component {
constructor(props) {
super(props);
this.onUpdateInput = this.onUpdateInput.bind(this);
this.state = {
dataSource : [],
inputValue : ''
}
}
onUpdateInput(inputValue) {
}
render() {
return <AutoComplete
dataSource = {this.state.dataSource}
onUpdateInput = {this.onUpdateInput} />
}
}
export default MaterialUIAutocomplete;
It's a typo, you are importing Autocomplete and using AutoComplete.
Use these ways to import AutoComplete:
import { AutoComplete } from 'material-ui';
Or
import AutoComplete from 'material-ui/AutoComplete';
Update:
To render material-ui component we need to add the default theme and styling, include these lines in your component, like this:
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
const muiTheme = getMuiTheme({});
Then render the AutoComplete inside MuiThemeProvider:
render() {
return <MuiThemeProvider muiTheme={muiTheme}>
<AutoComplete
dataSource = {this.state.dataSource}
onUpdateInput = {this.onUpdateInput} />
</MuiThemeProvider>
}
Use this:
import React, {Component} from 'react';
import AutoComplete from 'material-ui/AutoComplete';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
const muiTheme = getMuiTheme({});
class MaterialUIAutocomplete extends Component {
constructor(props) {
super(props);
this.state = {
dataSource : [],
inputValue : ''
}
this.onUpdateInput = this.onUpdateInput.bind(this);
}
onUpdateInput(inputValue) {
}
render() {
return <MuiThemeProvider muiTheme={muiTheme}>
<AutoComplete
dataSource = {this.state.dataSource}
onUpdateInput = {this.onUpdateInput} />
</MuiThemeProvider>
}
}
export default MaterialUIAutocomplete;
Note: MuiThemeProvider is not required to include inside each component, you can use this in main page and then you can use any material-ui component inside any component.
this looks like a migration issue to me - you want to use the material-ui 0.x AutoComplete, but you have installed the new material-ui v1.x.
as such, you need to follow the Migration steps and in order to use any v0.x component, put this wherever you create/declare your themes:
<MuiThemeProvider theme={theme}>
<V0MuiThemeProvider muiTheme={themeV0}>
{/*Components*/}
</V0MuiThemeProvider>
Because the new 1.5 theme is available via props, the old one through context, you need to include both for AutoComplete to have reference to the old theme. I wouldn't do this unless you really need something from the old library, such as the AutoComplete widget.
https://material-ui.com/guides/migration-v0x/

Carousel built with ReactSwipeableViews does not show items

I am trying to implement this carousel using material-ui and react-swipeable-views.
I have a carousel item that looks like this:
import React, {Component, PropTypes} from 'react'
export default class CarouselItem extends Component {
static contextTypes = {
muiTheme: PropTypes.object.isRequired
}
static defaultProps = {
href:'#'
}
constructor(props) {
super(props)
}
render() {
const carouselItemStyle = {
width:'100%',
height:'100%',
minHeight:'400px',
position:'absolute',
top:0,
left:0,
zIndex:-1,
opacity:1,
display:'block'
}
const {prepareStyles} = this.context.muiTheme
const {href,image} = this.props
debugger
return (<a href={href} style={prepareStyles(carouselItemStyle)}>
<img src={image}/>
</a>
)
}
}
I have a Carousel component that looks like this:
import React, {Component, PropTypes} from 'react'
import {v4} from 'node-uuid'
import CarouselItem from './CarouselItem'
import autoPlay from 'react-swipeable-views/lib/autoPlay'
import SwipeableViews from 'react-swipeable-views'
const AutoplaySwipeableViews = autoPlay(SwipeableViews)
export default class Carousel extends Component {
static contextTypes = {
muiTheme: PropTypes.object.isRequired
}
static propTypes = {
items:PropTypes.arrayOf(PropTypes.string),
autoplay:PropTypes.bool
}
static defaultProps = {
autoplay:false
}
constructor(props) {
super(props)
}
render() {
const carousel = {
overflow:'hidden',
position:'relative',
width:'100%',
perspective:'500px',
transformStyle:'preserve-3d',
transformOrigin:'0% 50%'
}
const carouselSlider = {
top:0,
left:0,
height:0
}
const {style:customStyles} = this.props
const style = Object.assign(
carousel,
carouselSlider,
customStyles
)
const {prepareStyles} = this.context.muiTheme
const SwipeImplementation = this.props.autoplay?AutoplaySwipeableViews:SwipeableViews
debugger
const carouselItems = this.props.items.map(function(item){
debugger
return <CarouselItem key={v4()} href="#" image={item}/>
})
return (<div style={prepareStyles(style)}>
<SwipeImplementation>
{carouselItems}
</SwipeImplementation>
</div>
)
}
}
I use the Carousel like this:
const items = [
'http://estruct.com.au/wp-content/uploads/2014/10/old-gccc-logo.png',
'http://www.activehealthycommunities.com.au/wp-content/uploads/2014/07/City-of_Gold-Coast_stacked_CMYK-01.jpg'
]
return (
<Carousel items={items} autoplay={true} />
)
I find that the carousel items do not appear, when I look in the developer tools, I find that transitions are happening but I do not see the items.
I have created a webpackbin with the code
I get an error in the bin that I do not have in my dev environment.
UPDATE:
If I remove the style for the a tag and change it to a div within CarouselItem:
//style={prepareStyles(carouselItemStyle)}
return (<div><img src={image}/></div>)
The images are displayed but are not full width. I notice that the transform css as well as height are determined using jQuery. How can we establish proper styling for the CarouselItem.
I think the problem is with your helloWorld.js. You're not creating the component correctly. Switching it to this is rendering the images for me.
export default class HelloWorld extends React.Component {
render() {
const items = [
'http://estruct.com.au/wp-content/uploads/2014/10/old-gccc-logo.png',
'http://www.activehealthycommunities.com.au/wp-content/uploads/2014/07/City-of_Gold-Coast_stacked_CMYK-01.jpg'
]
return (
<MuiThemeProvider>
<Carousel items={items} autoplay={true}/>
</MuiThemeProvider>
);
}
}

Resources