Greetings fellow denizens of StackOverflow. I am trying to write a react component which allows users to select a number (rating) from a drop down menu, which is then display and tracked persistently. However, I have a small problem. The computer doesn't like the "===" in my if statement. It says its an "unexpected token." What's the deal? Here's the if statement and everything that comes before it since I assume you don't need the rest.
import React, { Component } from "react";
const loggedRatingVar = localStorage.getItem("rating0");
class DropDown0 extends Component {
if (loggedRatingVar === null)
{
this.setState({displayRating: "?"});
}
else
{
this.setState({displayRating: loggedRatingVar});
}
Classes are not functions. Classes are not executable. Classes are CONTAINERS. They contain constructors, methods and properties. Any code inside a class has to be inside a method or constructor. (Well, the constructor is just a special method.)
This is basic JavaScript syntax and you'd do well to study the examples.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
You are defining a class component not a function.
I suggest to read the documentation here on how to do it properly.
Since it seems you are setting states you would want to put that on a function or React lifecycle methods (more about lifecycle methods here)
Do it like so. Just gave an example on what Jaromanda X commented.
class DropDown0 extends Component {
thisIsAfunction() {
if (loggedRatingVar === null)
{
this.setState({displayRating: "?"});
}
else
{
this.setState({displayRating: loggedRatingVar});
}
}
}
Related
This is how the components are arranged
class A extends React.Component {
state = {mode: 'create'}
abstract getRows() {
}
abstract getTitle(){
}
}
class B extends A {
getTitle(){
if(this.state.mode === 'create'){ return 'New';}
else {return 'Existing'};
}
}
And in test case:
jest.mock('componentAFile');
component = shallow(<B />);
component.setState({mode: 'create'});
expect(component.instance().getTitle()).toBe('New');
component.setState({mode: 'edit'});
expect(component.instance().getTitle()).toBe('Existing');
But state mode says undefined. What is the correct way to do this? How do we test such classes inheriting from base classes?
First, better don't use that inheritance approach. Composition is so many way better that I even cannot recall any cons of inheritance.
Second, using .setState you are literally accessing internal aka private data. Or in other words "implementation details". There are so many cases when it breaks suddenly(renamed property in this.state, refactored class component into function, decompose one component into several etc etc), that there are no reason to use it.
Third, the same is with testing internal methods. Again, it's implementation details, for both name, arguments ordering, result returned. And moreover, let's assume you never use that function in what component renders in render(). So test will pass, but component might be broken.
What can you do instead?
Provide prop(shallow(<B prop1={mockedValue} prop2={anotherValue} />);)
change prop(.setProps)
call callback(component.find('button').simulate('click'))
validate against rendering results: expect(component.find('.title').text()).toBe('New')
also we may want to validate whether some mocked external service/utility has been called(but your case probably does not need that; just want to have complete list)
I was looking for a way to bind react class methods to this in the constructor all at once, because I got tired of typing this._anotherFunction = this._anotherFunction.bind(this) 10 times for each component.
I haven't seen anyone else posting solutions for this and thought it would be useful to share my answer.
Interested to see if anyone else has similar implementations, or if there are any issues with the way I implemented.
Given the following React class functions:
_showModal() {}
_hideModal() {}
// etc.
In the constructor I added:
// bind all of the class's methods to the class
bindClassMethods.bind(this)([
'_showModal',
'_hideModal',
// etc.
]);
Here's the re-usable util function I wrote to pull this off:
export function bindClassMethods(classMethods = []) {
if (!_.isArray(classMethods)) {
console.error(`Need to pass an array to bindClassMethods().`);
return;
}
classMethods.map(fnc => {
if (!this[fnc]) {
console.error(
`Warning: func ${fnc} is not defined! It probably has been removed from this class' methods.`
);
} else {
this[fnc] = this[fnc].bind(this);
}
});
}
I found the console logs useful for reminding myself when I forgot to remove or update a function binding.
Revisiting this issue - the previous suggestion to use arrow functions as class properties have some drawbacks, including performance implications. (Albeit an arguably negligible performance implication, but one worth noting).
New Proposed Solution:
create a new class that extends Component, e.g. ComponentAutoBind
any sub-component that extends ComponentAutoBind will automatically have its own methods bound to the class instance
exclude React lifecycle methods from binding
See this gist for proposed solution
Working codepen example
I realize that extending Component may not be best practice but my implementation is only affecting the constructor - all other Component class properties are untouched.
Here are some links for the unconvinced:
https://medium.com/#forsakenharmony/you-should-maybe-mention-that-the-arrow-function-in-the-class-body-is-just-syntactic-sugar-c7bfb3383bef
https://blog.usejournal.com/arrow-functions-are-disrupting-react-components-63662d35f97b
https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36 - only discusses Render method but same principle applies to class properties
I'm interested to know how reactjs PropTypes work under the hood as I would like to implement something similar in an application I'm writing.
Specifically, I'm trying to create property validators in the same format as reactjs (i.e {type}.{isRequired} syntax).
Additionally, I hope to do it so that only one instance of each validation function exists at a time.
My current implementation is as follows:
// Interface
class PropTypes
{
static string(isRequired)
{
return isRequired ?
ConcretePropTypes.string_required :
ConcretePropTypes.string;
}
}
// Concrete prop validation
class ConcretePropTypes
{
static string(x) { return typeof x == "string"; }
static string_required(x) { return !isNan(x) && this.string(x); }
}
// Sample usage
var propTypes = { name: PropTypes.string(true) };
...but this demands the usage of arguments (i.e isRequired) to determine which validation function to return. As it is not intuitive what the boolean argument being passed in represents (unless the source code is looked at), I would prefer to use a syntax similar to reactjs - i.e string.isRequired - so that it removes any ambiguity in its usage.
All in all, what I'm looking for is information on how reactjs proptypes work and as such, how I can apply this to my own code. If the question title is misleading and needs changing, please let me know.
I'm trying to adapt code from a SO answer, with functions and variables written as below:
const getIntervals = n=> availability=> {
}
let availability = [
]
Are those normally fine to use in a react class (see below) or do they need to be rewritten?
class Calendar extends React.Component {}
The reason for asking is that I use a React implementation for Rails and do get an error including that function and variable naming pattern.
Pure Functions, which dont modify the passed value, are always fine to use anywhere.
Its also fine to use them in a React Class directly, but common functions like string modifications, array sorting algorithms, which you are using a lot across your app and classes should go in a separate module like
// my-helpers.js
export const countKeysInObject = (data) => {
if (typeof data !== "object" || Array.isArray(data)) return 0;
Object.keys(data).length;
}
some other file..
import { countKeysInObject } form 'my-helpers'
// And you can use it everywhere..
If you are using class and extending Component, you can use simple methods for most things:
class Calendar extends React.Component {
constructor(props) {
this.date = props.date;
}
render() {
return <span>{this.date.toString()}</span>;
}
}
Calendar.propTypes = {
date: React.PropTypes.date.isRequired
};
You cannot use methods for propTypes or anything that would be an initial field if you were using an object literal. Those need to be attached after the class has been declared (propTypes) or in the constructor (initial state).
I'm looking at some ES6 code and I don't understand what the # symbol does when it is placed in front of a variable. The closest thing I could find has something to do with private fields?
Code I was looking at from the redux library:
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'redux/react';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/CounterActions';
#connect(state => ({
counter: state.counter
}))
export default class CounterApp extends Component {
render() {
const { counter, dispatch } = this.props;
return (
<Counter counter={counter}
{...bindActionCreators(CounterActions, dispatch)} />
);
}
}
Here is a blog post I found on the topic: https://github.com/zenparsing/es-private-fields
In this blog post all the examples are in the context of a class - what does it mean when the symbol is used within a module?
I found the accepted answer was not enough to help me sort this out, so I'm adding a little more detail to help others who find this.
The problem is that it's unclear exactly what is the decorator. The decorator in the example given is not just the # symbol, it's the #connect function. Simply put, the #connect function is decorating the CounterApp class.
And what is it doing in this case? It's connecting the state.counter value to the props of the class. Remember that in redux the connect function takes two arguments: mapStateToProps and mapDispatchToProps. In this example, it's taking only one argument - mapStateToProps.
I haven't investigated this too much, but this appears to be a way to encapsulate your state-to-props and dispatch-to-props mappings so they accompany your components rather than being located in a different file.
It's a decorator. It's a proposal to be added to ECMAScript. There are multiple ES6 and ES5 equivalent examples on: javascript-decorators.
Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated.
They are commonly used to control access, registration, annotation.
What is #myDecorator()?
The # symbol in javascript stands for a decorator. Decorators are not present in ES6 so the in code you are working with the decorator is probably transpiled to an version of javascript which can be run in any browser.
What is a decorator?
A decorator extends (i.e. decorates) an object’s behavior dynamically. The ability to add new behavior at runtime is accomplished by a Decorator object which ‘wraps itself’ around the original object. A decorator is not just a concept in javascript. It is a design pattern used in all object oriented programming languages. Here is a definition from wikipedia:
In object-oriented programming, the decorator pattern is a design
pattern that allows behavior to be added to an individual object,
dynamically, without affecting the behavior of other objects from the
same class. The decorator pattern is often useful for adhering to the
Single Responsibility Principle, as it allows functionality to be
divided between classes with unique areas of concern
Why use a decorator?
The functionality of an object can be modified at runtime when using a decorator. For example, in your code you simply imported the decorator and added it to your CounterApp class. Now your CounterApp has dynamically added functionality Without you knowing the implementation details.
Example:
// decorator lights is a function which receives the class as an argument
let lights = function(tree) {
// The behaviour of the class is modified here
tree.treeLights = 'Christmas lights'
}
#lights // the decorator is applied here
class ChristmasTree {}
console.log(ChristmasTree.treeLights); // logs Christmas lights