calling a function using this.value - reactjs

I want to pass the appropriate makeData function into the data element in ReactTable according to which year is selected. I keep getting a syntax error and I'm not sure why it won't let me compile it as is.
My logic is this:
The select value has an onChange function that will call handleChange whenever a different year is selected. Once handleChange is called, it will set the value to the event target.
The data object will then pass to the "data" element in ReactTable as "this.value"

There's a lot of stuff wrong here:
Functional components don't have state. Use a class that extends React.Component if you need state
handleChange can't be placed inside of the JSX. Again, use a class and make that a method of the class
this.state.value has the function in a string. You probably want this.state = {value: makeData2014()};. You do this in your JSX as well. Wrap the function call in curly braces instead of strings like so: <option value={makeData2014()}>2014</option>
When you call setState, you're updating this.state.value, not this.value. Thus, you don't need this.value at all and you should remove it.
To top it off, you didn't add the specific error message, so I can't even be sure this is all of it.
Step one should be fixing up all of these issues. After that, if you still have any problems, update your question with the new code and the specific error message you're getting.

Related

Mobx async example does not render result after action

You can look at the issue via codesandbox
Codesandbox: https://codesandbox.io/s/great-frog-m2s7h
Context
I am trying to fetch some data and populate some variable and render the value in React, essentially following the documentation await/async + runInAction example: https://mobx.js.org/actions.html#asynchronous-actions
However, when the data is fetched, React actually does not re-render. However, if you edit the text in there(i.e. change hi to his or whatever, then you see the correct value appear.
Problem
What exactly am I doing wrong with the data fetching? Why isn't the observable value not being re-rendered correctly when its been assigned a value after some data has been fetched?
This is actually one of the limitations of Mobx.
From the docs:
make(Auto)Observable only supports properties that are already defined. Make sure your compiler configuration is correct, or as workaround, that a value is assigned to all properties before using make(Auto)Observable. Without correct configuration, fields that are declared but not initialized (like in class X { y; }) will not be picked up correctly.
Just initialize the title this.title=undefined and it will work.
Its a simple mistake. MobX can not compare data of title to something that dosent exist. Stuff should have default value of some sort, even a null. hence in a constructor you need to define title default value like
constructor() {
this.title = [],
makeAutoObservable(this);
}
or, if you wish, even null
constructor() {
this.title = null,
makeAutoObservable(this);
}
Basiclaly, whenever you create some observable variable in a store - you need to define its default value in a constructor above makeAutoObservable.
Here, a forked project of yours with juswt this 1 line change to make it work https://codesandbox.io/s/suspicious-noether-fnhjw

When do I need to use bind() in reactJS and react native

so when I create a class I it ususally look something like this
export default class SettingsIndex extends Component {
constructor(props) {
super(props);
this.state = {
testValue: 1,
};
}
myfunction(){
this.setstate({value: 2)
}
render(){
return(
........
Question 1:
To be honest, I am not sure when I really need to have the constructor, in my understanding is that I need to declare the constructor every time a class is receiving props from a parent component, is that assumption correction?
Question 2:
see myfunction() in some classes it works without issue, however in some classes I have I get an error saying ```this.myfunction' is undefined and I then I need to bind(this) in the constructor like this
this.myfunction= this.myfunction.bind(this);
I am not sure why in some class this is accessible and not other, any idea?
You need to use the constructor only when you need to have some initialisation logic which needs to run before the first render such as initialising refs, state or binding functions. You do not require constructor just beecause your component is receiving props, React itself can do that prop forwarding for you
For your case you can define state as a class initialiser too with proper babel setup and get rid of the constructor
export default class SettingsIndex extends Component {
state = {
testValue: 1,
};
myfunction(){
this.setstate({value: 2)
}
}
Now as far as the question about binding is concerned, you first need to understand how does a function receive its context or this variable.
The this argument to a function call is received as the reference of the object on which the function is called unless the function is defined as an arrow function in which case it inherits the this variable from its surrounding scope or this is explicitly overwritten by use of call, apply or bind methods
For Example, in the lifeecycle meethods of React, the this variable already points to the class instance and calling a function using this.myFunction() will causee the myFunction to receive the context of the class as the object on which it is called is this.
On the other hand when you assign the function to an event handler, you are assigning a reference to it and when the event occurs the function is ccalled on the window reference causing the this to be undeefined and thus nneeding you to use arrow function or explicit bind to supply proper context.
Check this SO post for more details on this keyword

React Native: This synthetic event is reused for performance reasons. Trying to pass state

I got two screens and want to pass the state from one to the other.
Simplified Screen 1:
import React, { Component } from 'react';
import { View, TextInput} from 'react-native';
import { buttons } from '../../components/buttons/Buttons';
export default class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
}
}
render() {
return(
<View>
...
<TextInput onChange={(input) => this.setState({username: input})}></TextInput>
...
<Button.main onPress={() => this.props.navigation.navigate('Register', {username: this.state.username})} title='Create Account'/>
</View>
)
}
}
Now, if I press the button, I want to pass this.state.username to the new screen. If I don't use onChange={(input) => this.setState({username: input})} and set a value for the username manually like this:
this.state = {
username: 'Test',
}
The value gets passed without problem and I can access it from the new screen. But when I try to change this.state.username while the TextInput changes and then pass this.state.username I get the following warning:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property isTrusted on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().
I don't know how to use event.persist() as proposed in the warning and the username doesn't get passed.
Sorry if this is a stupid question, but I couldn't find a solution and I'm a beginner. I would be glad if someone could help me with this :)
Try using onChangeText instead of onChange.
Adding on to accepted answer to provide a more elaborate explanation.
The behaviour observed is a combination React's intended design for events and how Javascript uses the pass-by-reference concept for passing objects into function:
React's design for events
The context here is that the function is passed to the onChange handler rather than onChangeText. onChange will pass an event object to the function while onChangeText passes a String. There is a catch to how event objects works in React.
React uses SyntheticEvent for events passed into event handlers and SyntheticEvents are pooled. So rather than creating new SyntheticEvent objects, these pooled objects are reused and all properties will be nullified after a callback is invoked (see React docs).
Pass-by-reference for objects in Javascript
In Javascript, when an object gets passed into a function as argument, the function receives the reference to that object as parameter rather than creating a copy of the object. Thus, modifying the object in the function will lead to the original object being modified.
Putting them together
Setting the passed event object parameter to state is basically storing the reference to one of the event objects in the pool into state. Since this object is reused (modified) and its content does not persist for long, the content retrieved from the reference stored in the state will quickly become irrelevant. This will cause the app to behave in unexpected ways.
The development environment detects this and thus give a warning.
The use of onChangeText - like the accepted answer recommended - will not only solve the problem but also seemingly be closer the original intention of the code.

Can't update state in react component

I have a component AddMenu
constructor(props) {
super(props);
this.state = {
menu: '',
make: '',
newCar: '',
}
this.addConfirmFuction=this.addConfirmFuction.bind(this);
}
Make the menu, make, model, year updated by changing the input text, it works.
handleChangeEvent(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
Then I want to combine everything in the state to "newcar" in the state
addConfirmFuction() {
let newEntered=[];
newEntered=newEntered.concat(this.state.menu);
newEntered=newEntered.concat(this.state.make);
this.setState({newCar:newEntered,});
}
After run the last line of code: this.setState (newCar: newEnteredCar), it is not updated, it is still ''. I looked at lots of documents and couldn't figure out...I have bind the function in the state constructor, I have used setState function, but couldn't update the state.thank you in advance.
Did you check if the state values "make" and "menu" are really not empty inside "addConfirmFunction()"?
Also, from your code, it looks like "make" and "menu" are just strings. Any reason for "newCar" being set with a value of type array? If it need not to be array, then this.state.make + this.state.menu would suffice I guess!
Edit:
I think I got the problem. If you are checking the state value immediately after the line is called, then you might not see the new value there since setState is an async function in React. (For performance gains). Please read this stack overflow link. There are lots of article which talks about it.
If you want to see the new value, since this setState calls for a render, keep a breakpoint at render method and check if the value of newCar is available there.

How can I tell when this.setState exists in ES6?

I have been struggling with trying to migrate my React code from ES5 to ES6. As I have found out by now, this is no longer automatically bound which causes all sorts of hell.
I am trying to figure out by trial and error what objects are being passed around. So far I can find everything and adjust accordingly. However when it comes to this.setState I am having problems because it is not visible in console.log!!!! See screenshot in ES5:
and here is the same kind of code in ES6:
Please teach me how to fish i.e. help me figure out how to understand when an object has this.setState or not?
things i have tried
from googling around i understand you might be able to default bind everything by changing the base component. unfortunately this did not work when it came to this.setState. It looks identical to the ES5 version of this in console so I concluded that setState is still not being bound somehow
To oversimplify how this works in JS:
If you call a function as an object method (e.g., instance.foo()) then this refers to that object instance.
If you call a function by itself (e.g., foo()), then this is either undefined or the global object, depending on whether strict mode is in effect.
If you take a reference to an object method then call it, that means you're calling it by itself, even though it was originally an object method. (E.g., var bar = instance.foo; bar();.
Again, this is an oversimplification; MDN has details.
As this applies to React, and as explained in the React documentation on "Handling Events":
You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
In your code, you render your RawInput as
<RawInput value={this.state.value} updateValue={this.updateValue}/>
You're passing a reference updateValue function in as a simple function, so this will not be bound within updateValue.
Basically, any time you pass a function as a React prop, unless you've bound it yourself, it's likely an error. The symptom is typically that this is undefined. In your code, it's a little more complicated:
this.props.updateValue(modifiedValue);
The RawInput's updateValue property is the unbound function App.updateValue, but because you're invoking it as this.props.updateValue, it's being called as if it were a method of this.props - so this refers to the RawInput's props. That's why your console.log is showing an object with only two properties (start and updateValue): it isn't that setState isn't bound or went away, it's that updateValue wasn't bound, so this isn't what you expect within updateValue.
To fix the issue, as the React docs explain:
Use a fat arrow function: updateValue={(value) => this.updateValue(value)}
Use the experimental property initializer syntax: Replace updateValue(modifiedValue) {...} with updateValue = (modifiedValue) => {...}.
Not mentioned in the React docs, but an approach I often use: Bind updateValue yourself. For example:
constructor(props) {
super(props);
this.updateValue = this.updateValue.bind(this);
}
you can replace console.log with this:
console.shallowCloneLog = function(){
var typeString = Function.prototype.call.bind(Object.prototype.toString)
console.log.apply(console, Array.prototype.map.call(arguments, function(x){
switch (typeString(x).slice(8, -1)) {
case 'Number': case 'String': case 'Undefined': case 'Null': case 'Boolean': return x;
case 'Array': return x.slice();
default:
var out = Object.create(Object.getPrototypeOf(x));
out.constructor = x.constructor;
for (var key in x) {
out[key] = x[key];
}
Object.defineProperty(out, 'constructor', {value: x.constructor});
return out;
}
}));
}
any way, regarding your question, you can add a method like this:
updateValue = () => {...}
in m POV - es6 is cool and great. React components by es6' classes are useless. stick with createClass and you'll be fine (and have mixins if you want!)
Try Object.prototype.hasOwnProperty(). For example:
var X = function() {};
X.prototype.setSomething = 'a';
var x = new X();
x.setSomething; // log 'a' here
x.hasOwnPrperty('setSomething') // log false here
In your case, just console.log(this.hasOwnProperty('setState')).
You have to bind your updateValue function with the component in order to have the correct context (this).
In your case, your parent class BaseComponent allows you to use the herited method _bind like that :
class App extends BaseComponent {
constructor(props){
super(props);
this.state={value:'start'};
this._bind('updateValue');
...

Resources