I am facing the following issue while using AceEditor react component https://github.com/securingsincity/react-ace
I am using AceEditor as user input, after user enters code, he(she) presses the Run button. (see the picture) How do I extract the text that users enters from AceEditor component ?
It's not necessary to use onChange.
<AceEditor ref="aceEditor" />
this.refs.aceEditor.editor.getValue()
You need to subscribe to the onChange event (explained in the docs) and store the value passed into the callback somewhere, perhaps in the component's state if the Run button is on the same page. Then, when user clicks the button just retrieve it via this.state.xxx
With the latest React v16.12+ this.refName.current.editor.getValue() works to get string value which can be parsed using JSON.parse.
Ref should be instantiated as:
constructor(props) {
super(props);
this.refName = React.createRef();
}
and passed to AceEditor component:
<AceEditor
ref={this.refName}
/>
AceEditor provides an onChange event which you can use to retrieve the current content of the editor whenever the user changes it and then store the value in your own data store or your component's state.
This way, you are able to retrieve the value whenever you need it.
More about the editor's properties.
The readme also provides an example, demostrating its usage.
You need to bind this state to the onchange function in constructor of class.It worked for me.
constructor(props){
super(props);
this.state = {code:"code"};
this.onChange = this.onChange.bind(this);
}
onChange(newValue) {
this.state.code = newValue;
alert(this.state.code);
}
Ace Editor's Onchange is
onChange = {
this.onChange
}
Related
I'm building a React App. I don't have a backend server. Instead, I used a .json file called securities.json as the backend server. The .json file list the securities and the price list in each security.
What I am attempting to do is to submit the updated price list to the securities.json on App.js, a parent component, from its child component. I noticed that when I add a new price in the Price Popup window and then close it but rechecked the Price Popup window again. The new price that I entered disappeared. I couldn't figure out how to solve it. I'm trying to pass it up to App.js as one developer suggested.
Can someone please take a look at my code in CodeSandBox?
https://codesandbox.io/s/github/kikidesignnet/caissa
Two solutions:
Use Redux: https://react-redux.js.org/
Use reacts context system: https://reactjs.org/docs/context.html
you can also pass an update function as props to your child component which updates the state of the parent.
My guess is price list is set in constructor. There the state is set from props. On change of props, the price list state is not updated as setting state happens in constructor which executed only once. You need to update state when ever props get changed.
This is the code I am talking about
constructor(props) {
super(props);
this.state = {
priceArr: this.props.pricelist,
// newPriceArr: this.props.updatePrice,
showPricePopup: false,
addPricePopup: false,
isToggleOn: true,
date: props.date || "",
number: props.number || ""
};
}
You may need to use getDerivedStateFromProps to set state when props change.
i saw similar questions but can't get some solution.
i have some input when you paste some text to input i'm trying to set it to state and render this text. But when paste in first time state not change in second time when paste everything works.
I don't understand why it happen i already used some setTimeOut function too for it but not helped.
here is my code:
import React from "react";
import { render } from "react-dom";
class App extends React.Component {
constructor() {
super();
this.state = {
no: ""
};
}
pasteSomeText = e => {
this.setState({
no: e.target.value
});
};
render() {
return (
<div style={styles}>
{this.state.no}
<input onPaste={event => this.pasteSomeText(event)} />
</div>
);
}
}
render(<App />, document.getElementById("root"));
Here is codeSandBox example: https://codesandbox.io/s/1-react-hello-world-tvscf?fontsize=14
To get the data from the event, use e.clipboardData.getData('text'). See https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event
e.target.value gives you the value for the text field before it updates with the paste data, so you can cancel/modify the paste if you want.
pasteSomeText(e) {
this.setState({
no: e.clipboardData.getData('text')
});
};
Side note: with the call from the HTML, you don't need to use this arrow function (which uses more memory), see my example above
Basically the reason why you get empty state on firts onpaste call is that onpaste fires before the input's value is changed. So you get empty event.target.value and for all other calls you get previous value.
And if you still decide to keep going with onpaste you should keep in mind that you can get pasted value with event.clipboardData.getData('Text') but it can differ from what have been pasted in input because of different behavior of clipboardData for different input types.
https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
So for work with clipboard data I will recommend to use DataTransfer module from https://www.npmjs.com/package/fbjs to get more consistant behavior in different systems and browsers.
Is a diferente kind of event you will need to get the clipboard data from the event and set it to the state
const value = e.clipboardData.getData('text')
use
onChange
instead of using
onPaste
Updated https://codesandbox.io/s/1-react-hello-world-h2jgv
So I have this application which uses Redux to store some data. Then I have the Search component, which I originally wanted to be a plain dumb component. However, there is an input field whose value I would like to access and pass on to do something with it. However, I am not sure how to manage the value of this input field, that is, how to access it & where to store the value. I want to use Redux and be consistent, so that's my main problem. I have found the following solution (which works), but this does not look like Redux to me anymore? Am I violating any Redux specific rules with this?
On the other hand, how would I do it with Redux? With a reducer & action etc. just for this one input field in one component? This seems like a bit too much, but please enlighten me!
class Search extends React.Component{
constructor(props) {
super(props);
this.state = {
username: ""
};
this.handleUsernameChange = this.handleUsernameChange.bind(this);
}
handleUsernameChange(evt) {
console.log("Helo" + evt.target.value);
this.setState({
username: evt.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log("Hello" + e);
/* Do something... */
}
render() {
// Return JSX via render()
return (
<div className="">
<h1>Youtube Link</h1>
<input className="form-control" onChange={this.handleUsernameChange}></input>
<button className="btn btn-large btn-positive" onClick={this.onSubmit}>Download</button>
</div>
);
}
}
// Export Search
export default Search
"I want to use Redux and be consistent, so that's my main problem."
That's a valid reason to use Redux for this use case. But it is also fine to use combination of Redux and local component state in your application. I think this is a perfect example on when local component state is a good solution. I wrote a blog post on this topic. If you want, you can take a look here: http://blog.jakoblind.no/2017/02/08/is-using-a-mix-of-redux-state-and-react-local-component-state-ok/
On the other hand, how would I do it with Redux? With a reducer & action etc. just for this one input field in one component? This seems like a bit too much, but please enlighten me!
Yes, this is how you would do it with Redux. If you need the the username value anywhere else in your app, then this is the approach you should take.
If you don't want to write your own actions and reducer and everything for it, you could look into redux-form to handle it for you, but it might be a bit overkill if there is not much other input required from the user.
If you only need it when you hit that button right below it, then what you have is fine as you can just raise your action with the value from the components state, e.g,
onSubmit(e) {
e.preventDefault();
console.log("Hello" + e);
/* Do something... */
this.props.downloadTheThing(this.state.username)
}
where downloadTheThing is mapped in your mapDispatchToProps function when connecting the component (assuming you are using react-redux).
It is definitely fine to use local state in Redux.
From the code snippet you shared, you don't even need to use a local state.
constructor(props) {
...
this.username = '';
...
}
onSubmit() {
console.log('Hello ' + this.username);
}
render() {
return (
...
<input type="text" onChange={e => this.username = e.target.value} />
...
);
}
<input className="form-control" onChange={this.handleUsernameChange}></input>
that is your input field. first thing todo when you work on input in react is to set the value and then apply onChange. with value we will assign the state of the input to the state of the component so we will get single source of truth.
since you want to work on redux store, I assume you already have your redux store, reducers and actions set in your application. reducers hold the state and you send message to reducers via dispatch(). You access to dispatch() on this.props.dispatch() once you define connect() (). By default, a connected component receives props.dispatch()
import React from "react"; //anywhere you are using jsx, u should import this
import { connect } from "react-redux";
import setInputAction from "relative path" //actions are the messages that you send to reducers. reducers change the state based on the actions.
//this allows you access to state in Redux-store via the props.
const mapStateToProps = state => {
return {
reduxState: state
};
};
export default connect(mapStateToProps)(Search);
this code is kinda configuration of your component to communicate with the redux-store.
Now let's focus on input field. we have to set the value:
<input
type="text"
value={this.props.reduxState.input}// i assume you have `input:""` in the state. u can name anything you want.
onChange={e => {
this.props.dispatch(setInputAction(e.target.value));//we are sending e.target.value to the reducer via dispatch().
}}
/>
setInputAction is just an object that sent to reducer. Reducers are already defined what to do under certain actions. So you just send the message and reducer will change the state accordingly.
I have React Redux working to change my child component's classname, but I do it via
//Subscribe with our function that sets our state
this.props.store.subscribe( this.onSelectChange );
(where the onSelectChange is a function in my component that changes a property on its state.
According to the redux docs, I should instead be using "a view binding library" like ReactRedux's connect method. But every tutorial is incredibly complex. They're hard to understand and appear to be about 5 times more code than what I need to use right now. Using Redux directly, I have about 6 lines of total code.
How can i simply use the "proper" way to make my child component change its classname?
If really all you need is to update a classname on click, React is perfectly capable of doing this without involving the Redux store.
The whole idea with React is that each component has some state object, and a render function to turn the state into markup. If you want to change your view, you should change the state and let React call render again. Take the following example which toggles the classname of a button (not tested):
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
highlighted: false
}
this.buttonClicked = this.buttonClicked.bind(this);
}
buttonClicked() {
var highlighted = !this.state.highlighted
this.setState({
highlighted: highlighted
})
}
render(){
var classname = this.state.highlighted ? "highlighted-btn" : "normal-btn"
return (
<button onClick={this.buttonClicked} className={classname} />
)
}
}
We trigger render by calling setState, in which we use the state to determine the classname for the button.
solution 1
well, if you change className because you want different style.
I will suggest you can use setState in its childComponent instead.
here is for your reference
solution 2
on the other hand, if you want to use Redux to achieve that.
you probably need to have a reducer first. let's say selectState
and then you need an action. here we name it changeSelectState
now, we can use connect from react-redux on the container component
and pass this method down to that presentational component. that's it.
So, the flow you can do is
add a reducer for storing data
add an action for changing the data
import that data and action via connect into container component
pass them down to presentational component
click and change the value via that action
This question relates to Redux Form v6.0.0 (in time of writing this question it is v6.0.0-alpha.15).
How can I get form validation status (like pristine, submitting, invalid) from outside of form component ?
Let me give an example. This is "classical redux-form" pseudo-structure:
<Form(MyExampleForm)>
<MyExampleForm>
<input name="title" ... />
<submit-button />
...where <submit-button> in JSX looks like this:
<button type="submit" disabled={pristine || submitting || invalid} >Save</button>
But in my application, my submit button must be outside of the form, placed on different place in the application (let's say in application header, on the top of whole application).
How can I get those pristine, submitting, invalid from outside of Redux-Form? (Without really nasty hacking, if possible :-))
How can I submit that form?
Just decorate another component with same form name and you have access to same state variables there. Also you can pass it onSubmit function from parent and be able to submit all the Field values from wherever you define them as they are all from redux state, not HTML of current form instance. (it is kind of "hacky" way, but it feels right)
The submit function is defined from parent, not shared in state, so you can have it different for every instance.
class MySubmitForm extends React.Component {
render() {
return (
<button
onClick={this.props.handleSubmit}
>
{this.props.pristine ? 'pristine' : 'changed'}
</button>
)
}
}
export default reduxForm({
form: 'myFormName'
})(MySubmitForm);
redux-form works with React Redux to enable an html form in React to use Redux to store all of its state.
If "outside of Redux-Form" means still redux application, you can try to store those properties in state by dispatching some actions.
In forms: you're detecting whats happening (when its invalid etc), dispatch an action to modify a state,
In "outside" part: you're passing a proper property to component (with those you need) and depends on that you disable a button.
in latest redux-form version 6.0.2:
it is possible to access form state pristine, submitting, invalid via selectors http://redux-form.com/6.0.2/docs/api/Selectors.md/
it is possible to export redux-form action creators http://redux-form.com/6.0.2/docs/api/ActionCreators.md/
Maybe you can have a look at the Instance API of redux-forms. It provides access to a submit() method on an instance of your decorated form component. There is also a pristine Boolean property and an invalid Boolean property available (there is a request to expose the submitting property too).
There is an example here : http://redux-form.com/5.3.1/#/examples/submit-from-parent?_k=jgv0m4 (example is for 5.3.1, but the process is similar with v6 using the Instance API)
The basic idea is that by adding a ref="myExampleForm" to your form, you can pass it around with this.refs.myExampleForm. You can then check properties of the instance or call the submit() method (or any other method exposed).
Now is easier to do this. You can call the Submit action in the standalone component that has the button.
See this example:
https://redux-form.com/7.1.2/examples/remotesubmit/
If we are talking about just submitting the form, then you should provide {withRef: true} option to your redux connect() function.
Consider Row component that has child RowDetail component which has information that should be saved from Row.
RowDetail in this case could be created like this:
import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';
const RowDetailForm = reduxForm({form: 'row-detail-form'})(RowDetail);
export default connect(mapStateToProps, null, null, {withRef: true})(RowDetailForm);
Then, in your parent component (Row) you create your form with ref attribute:
<RowDetailForm ref={'rowDetailForm'} .../>
Submitting now is 'easy':
onSave() {
this.refs.rowDetailForm.getWrappedInstance().submit();
}
If we are talking about pristine and other form properties, then you could try to get them from your mapStateToProps function in your parent component.
const rowDetailFormName = 'row-detail-form';
const mapStateToProps = (state) => ({
rowDetailForm: state.form[rowDetailFormName]
});
But this way seems a bit hacky because as I understand redux-form API all form states were never meant to be accessed directly. Please correct me if I am wrong
I had to tackle this issue recently. I ended up passing a callback to the form, which is invoked every time the properties I'm interested in change.
I use the componentDidUpdate life cycle method to detect changes.
This should work on any version of the library.
Here is a post with sample code - http://nikgrozev.com/2018/06/08/redux-form-with-external-submit-button/