Connecting react-draft-wyswig to redux-form - reactjs

I'm trying to add to redux-form field of type Editor from react-draft-wyswig. As I read from redux-form docs I need to connect it by value and onChange properties in Field component (from redux-form).
I built a component with additional property value which stores a html code of current wyswig-editor:
class WYSWIGField extends Component {
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty(), value: '' };
this.onChange = this.onChange.bind(this);
}
onChange(editorState){
this.setState({ editorState: editorState,
value: draftToHtml(convertToRaw(editorState.getCurrentContent()))});
//console.log(this.state.value);
};
render() {
return (
<div>
<Editor
editorState={this.state.editorState}
onEditorStateChange={this.onChange}
/>
</div>
);
}
}
My form:
<form onSubmit={handleSubmit(this.props.addPost)}>
<Field name="editor" component={WYSWIGField}/>
<button type="submit">Add post</button>
</form>
Export:
export default connect(null, { addPost })(
reduxForm({form: "AddPostForm"})(Posts));
And action creatow where I always receive empty object without my values from editor:
export function addPost(prop) {
console.log("prop", prop);
return{
type: ADD_POST,
payload: prop
};
}
Could somebody help me with this? Where I did mistake?
Thank you

Related

React this.props.function is not a function when passing in functions from parent component to child component

Im new to react and trying to follow this https://www.youtube.com/watch?v=I6IY2TqnPDA&t=538s tutorial video on Youtube to create a todo list app. Basically it passes addToDo function into the child component ToDoForm as props and then gets called in the handleSubmit of Child the component.
However im keep getting this TypeError: this.props.onSubmit is not a function. I have tried binding the function but the same error keeps popping up. When i console.log(this.props), it says undefined.
parent component:
class App extends Component{
state = {
todos: []
};
addToDo = todo => {
this.setState({
todos: [todo, ...this.state.todos]
});
};
render(){
return (
<div>
<TodoForm onSubmit={this.addToDO} />
{JSON.stringify(this.state.todos)}
</div>
)
}
}
export default App;
child component:
import React, { Component } from 'react';
import shortid from 'shortid';
export default class TodoFrom extends Component {
state = {
text: ""
};
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = (e) => {
e.preventDefault();
this.props.onSubmit({
id: shortid.generate(),
text: this.state.text,
complete: false
});
this.setState({
text: ""
});
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name = "text"
value={this.state.text}
onChange={this.handleChange}
placeholder="todo..."
/>
<button onClick={this.handleSubmit}>add todo</button>
</form>
)
}
}
Someone please help
JavaScript is case sensitive so by passing in this.addToDO, you're referencing a non-existent function. Change
<TodoForm onSubmit={this.addToDO} />
to
<TodoForm onSubmit={this.addToDo} />

ReactJs - Countdown reset unexpectedly

I've used Countdown on my project and it works like a charm. but when I combined it with simple input, it would be restart whenever my input changes. I want to restart it only and only if time over. Here is my code:
import React from 'react';
import { Input } from 'reactstrap';
import Countdown from 'react-countdown-now';
import { connect } from 'react-redux';
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
code: '',
disabled: false,
};
this.update = this.update.bind(this);
}
update(e) {
this.setState({ code: e.target.value });
}
render() {
return (
<div>
<Input
className="text-center activationCode__letter-spacing"
maxLength="4"
type="text"
pattern="\d*"
id="activationCode__input-fourth"
bsSize="lg"
value={this.state.code}
onChange={this.update}
/>{' '}
<Countdown date={Date.now() + 120000} renderer={renderer} />
</div>
);
}
}
const renderer = ({ minutes, seconds, completed }) => {
if (completed) {
return <p>reset</p>;
}
return (
<p>
{minutes}:{seconds}
</p>
);
};
const mapStateToProps = state => ({
user: state.auth,
});
export default connect(
mapStateToProps,
null,
)(Foo);
Any suggestion?
The reason why your counter is restarting, is because when you change the input field you're updating your state. Updating the state will cause a rerender which ultimately executes the Date.now() function again.
A solution for your problem would be to move the date for your countdown up in your constructor, so it is only set once, and then in your render function reference it through state.
constructor(props) {
super(props);
this.state = {
code: '',
disabled: false,
date: Date.now() + 120000
};
this.update = this.update.bind(this);
}
...
render() {
return (
<div>
<Input
className="text-center activationCode__letter-spacing"
maxLength="4"
type="text"
pattern="\d*"
id="activationCode__input-fourth"
bsSize="lg"
value={this.state.code}
onChange={this.update}
/>{' '}
<Countdown date={this.state.date} renderer={renderer} />
</div>
);
}

Semantic TextArea not editable with initial text

React Semantic - TextArea
I have initial value
which is showing in the textArea but its not editable anymore.
Any solution?
codepen example:
[1]: https://codepen.io/as3script/pen/VRepqv?editors=1010
You can use state for this purpose
const {
TextArea,
} = semanticUIReact
class App extends React.Component {
constructor(props){
super(props);
this.state={
value: "initial text which I would like to edit" // set initial state
}
}
onChange(e){
this.setState({ value: e.target.value })
}
render() {
const { value } = this.state;
return (
<div>
<TextArea
rows={4}
style={{'width': '550'}}
onChange={(e) => this.onChange(e)}
value={value} //render changed state
/>
</div>
)
}
}
// ----------------------------------------
// Render to DOM
// ----------------------------------------
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
ReactDOM.render(<App />, mountNode)

Passing a function from an object to the component to edit the state

I have a FIELDS object containing settings for many fields (also objects) that will be used to build the input fields in my page with the function renderField. Some of these fields need a function to edit the state of the component. I need this to be able to do some sort of autocompletion while the user is filling the form.
The code looks like this.
import React from 'react';
import {Field,reduxForm} from 'redux-form';
import {connect} from 'react-redux';
import _ from 'lodash';
// objects that will be used to create the form
const FIELDS = {
first_name: {
type: 'text',
label: 'First name',
onChange: function(e){
this.setstate({first_name:e.target.value})
},
last_name: {
type: 'text',
label: 'last name',
onChange: function(e){
this.setstate({last_name:e.target.value})
},
...
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
first_name : '',
last_name : '',
birth : '',
sex:''
};
}
renderField(field) {
const fieldConfig = FIELDS[field.input.name];
const {meta: {touched, error}} = field;
return (
<div className={`form-group ${touched && error ? 'has-danger' :''}`}>
<br />
<label>{fieldConfig.label}</label>
<input
{...fieldConfig}
{...field.input}
/>
<div className='text-help'>{touched ? error : ""}</div>
<br />
</div>
);
}
onSubmit(){
...
}
render() {
const {handleSubmit} = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{ _.keys(FIELDS).map( key => {
return <Field name={key} key={key} component={this.renderField} />;
})
}
<button type='submit'>Submit</button>
</form>
</div>
)
}
}
export default reduxForm({
// validate,
form: 'Form example'
})(
connect(null)(App)
);
I know that I can't call this.setState() this way, but I have no idea how I could bind the function inside the object inside the component. I did a lot of research and can't seem to find a solution. I don't know if it's because I'm not following good practices or not.
Thanks in advance
I found a solution. Instead of doing something complicated I just moved the function from the object directly in the render function in the component, making the connection to the state possible.

React-Redux Form not returning values

I have setup React-Redux form, but upon submit I am getting an empty object in the console.log()
Here is my code
import React from 'react';
import {reduxForm} from 'redux-form';
import {stockSave} from '../actions/actions';
class Stock extends React.Component {
customHandler(values){
console.log(values);
//this.props.stockSave(values);
}
render() {
const {fields: {id}, handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit(this.customHandler)}>
<input type="text" {...id} />
<button type="submit">Submit</button>
</form>
)
}
};
export default reduxForm({
form: 'myForm',
fields: ['id']
}, null, {stockSave})(Stock);
After submitting the form, I get empty object in the console. Here is the screenshot https://www.screencast.com/t/lzNoKPwsLU
Any help regarding this problem? Thanks!
You need to add a constructor in your class and bind your customHandler function.
class Stock extends React.Component {
constructor(props) {
super(props);
this.customHandler = this.customHandler.bind(this);
}
customHandler(values){
console.log(values);
//this.props.stockSave(values);
}
render() {
const {fields: {id}, handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit(this.customHandler)}>
<input type="text" {...id} />
<button type="submit">Submit</button>
</form>
)
}
};
export default reduxForm({
form: 'myForm',
fields: ['id']
}, null, {stockSave})(Stock);
And why are calling handleSubmit from pros and passing your customHandle as parameter?
I think that you want to call your handleSubmit this would be better:
customHandler(values){
this.props.handleSubmit();
console.log(values);
//this.props.stockSave(values);
}

Resources