ReactJS: Why can't I access variables outside the .map method? - reactjs

How can I access the constant answer from within this map method's function?
If I pass this to the map method, this.props.answer is defined, but answer is still undefined.
export default class QuestionList extends React.Component {
static propTypes = {
question: ImmutablePropTypes.map,
answer: ImmutablePropTypes.map
};
render() {
const question = this.props.question;
const inputs = question.get('inputs'); // [Input1, Input2, Input3]
const answer = this.props.answer;
const listBody = inputs.map((input, index) => {
console.log(answer); // Uncaught ReferenceError: answer is not defined
});
return (
<div>{listBody}</div>
);
}
}

Related

TypeError: Object(...) is not a function - function to return deep copies of objects

I'm having a TypeError: Object(...) is not a function on the following scenario:
In order to initialize the state of a component with a given Article (that will be fetched from the backend in componentDidMount) I'm doing this
// ArticlePage.tsx
import { Article, buildArticle } from "../types";
// interfaces Props and State are properly defined above
export class ArticlePage extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loading: true,
article: buildArticle(),
//...
}
}
}
In the types module, I define the type for Article, a default article object to initialize state and a function to return deep copies of the default article object:
// types/Article.ts
import { buildUser, User } from ".";
export type Article = {
id: number;
user: User;
// ...
};
const articleSkeleton: Article = {
id: 0,
user: buildUser(), // <------ TypeError points to this line
//...
}
export const buildArticle = (): Article => _.cloneDeep(articleSkeleton); // _ is lodash
Same thing for User
// types/User.ts
export type User = {
id: number;
};
const userSkeleton: User = {
id: 0,
}
export const buildUser = (): User => _.cloneDeep(userSkeleton); // _ is lodash
Both of them under a types directory with an index.ts like this:
// types/index.ts
export * from "./Article";
export * from "./User";
If I define the articleSkeleton object like this instead of using the buildUser function
// types/Article.ts
const articleSkeleton: Article = {
id: 0,
user: _.cloneDeep(userSkeleton), // deep clone the object directly here instead of calling the buildUser() function to do it
//...
}
export const buildArticle = (): Article => _.cloneDeep(articleSkeleton); // _ is lodash
it works!
But in my head those are equivalent things...
Can someone explain me why they are not, why one works and the other doesn't?
Is what I am doing a bad practice and, if so, how should I handle this?
If I'm defining a type and a function to create objects of that type, would it be better to simply create a class instead?
What would be the pros and cons of that?
Edit:
I've tried switching the order of the exports of Article and User in the index.ts file and it works now...
// types/index.ts
export * from "./User";
export * from "./Article";
Could it be that, when it was running the buildUser() function in Article, the userSkeleton object didn't exist yet?
It seems that the order of your constants is incorrect.
Move the declaration of buildUser() before articleSkeleton, or alternatively use a function instead of a const.
const buildUserOK = (): User => userSkeleton
const articleSkeleton = {
id: 0,
userError: buildUserError(),
userOk: buildUserOK(),
userOk1: buildUserFun(),
//...
}
type User = {
id: number;
};
const userSkeleton: User = {
id: 0,
}
const buildUserError = (): User => userSkeleton
function buildUserFun(): User {
return userSkeleton;
}
Playground link

React this.props."function" is not a function

I spent a lot of time on stack overflow and I still can't find my error despite my research. I want to user a method from a external librairy called "mxGraph", and I want to add a listener of my graph component
Here is my error: "this.props.graph.getSelectionModel is not a function"
Here is my code:
class StyleModificationBar extends Component {
constructor(props) {
super(props);
this.state = {
fontValue: 16,
};
}
componentDidMount() {
this.initListener();
}
initListener = () => {
this.props.graph.getSelectionModel().addListener(mxEvent.CHANGE, this.onSelected);
};
onSelected = evt => {
console.log(evt.cells[0]);
};
}
I've tried everything, bind my initLister function in the constructor and I've tried again and again to bind my initLister function in the constructor and I've tried again and again.
Could someone help me?
The behavior is very strange, the first console.log (the one in the constructor) returns an empty object while the one in the increase function returns my mxGraph object and this function works perfectly.
class StyleModificationBar extends Component {
constructor(props) {
super(props);
this.state = {
fontValue: 16,
};
console.log(this.props.graph); // This one print a empty object
}
increaseFontValue = () => {
console.log(this.props.graph); // This one print a full mxGraph object
let cellProperties = this.props.graph.getCellStyle(this.props.graph.getSelectionCell());
this.setState({fontValue: parseInt(cellProperties.fontSize) + 1},
() => {
this.props.graph.setCellStyles("fontSize", this.state.fontValue)
})
}
decreaseFontValue = () => {
let cellProperties = this.props.graph.getCellStyle(this.props.graph.getSelectionCell());
this.setState({fontValue: parseInt(cellProperties.fontSize) - 1},
() => {
this.props.graph.setCellStyles("fontSize", this.state.fontValue)
})
}

React Redux Props Undefined During Variable Assignment

Why is it when I assign the props to a JSX variable, it outputs as undefined? Is this normal? Or is there some other code in my program that would be causing this issue?
const { foo } = this.props;
console.log(this.props);
console.log(foo);
class Library extends Component {
componentDidMount() {
M.AutoInit();
}
render() {
const { foo } = this.props;
console.log(this.props);
console.log(foo);
return <div className="container"></div>;
}
}
const mapStateToProps = state => {
return {
cred: state.cred.tabs
};
};
You are trying to destructure property foo from this.props.
But according to your logs, this.props does not seem to contain any foo property.
const { foo } = this.props; is the same as writing const foo = this.props.foo;, which, it seems, is not a value in your props.
If that's not intended and you are instead trying to assign the whole props object to the foo variable, the correct syntax would be const foo = this.props;.

React: How to access the props object outside its class?

I am not sure how to access the props object outside the context of a receiving child, is there any way? Here is a minimal test file (Jest and Enzyme) I setup to experiment with. I get a syntax error where I try to pass this.props.propNumber in:"this is a reserved word"
const React = require("react");
const enzyme = require("enzyme");
const Adapter = require("enzyme-adapter-react-16");
enzyme.configure({ adapter : new Adapter() });
// simple component with an increment method
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
testIncrement : 1
};
}
handleIncrement = (incrementSize) => {
this.setState({
testIncrement : this.state.testIncrement += incrementSize
})
};
render() {
return (
<div>
Test
</div>
);
}
}
const wrapper = enzyme.shallow(
<Foo
propNumber={5}
/>
);
test('prop passage into shallow instance', () => {
wrapper.instance().handleIncrement(this.props.propNumber);
expect(wrapper.state('testIncrement')).toEqual(6);
});
You know what the prop is because you are passing it in, why do you need to access it from the class?
const incrementSize = 1;
const propNumber = 5;
const wrapper = enzyme.shallow(
<Foo
propNumber={propNumber}
/>
);
test('prop passage into shallow instance', () => {
wrapper.instance().handleIncrement(incrementSize);
expect(wrapper.state('testIncrement')).toEqual(propNumber + incrementSize);
});
And your handleIncrement function doesn't take an array, so no reason to pass it one.
In your parent component file, export the value, and then in your child component file, import the value

Should one use const when declaring an arrow function in React class

Inside a react class component, should one use a const/let to declare an arrow function, or they should be emmited:
class ReactComp extend Component {
const sayHello = () => {
return 'Hello';
}
sayBye = () => {
return 'Hello';
}
render() {
<div>
{this.sayHello}
{this.sayBye}
</div>
}
}
In this example, is sayBye declared correctly? (Without a const)
In addition, why outside the class, such a declaration does not work?
class ReactComp extend Component {
render() {
<div>
{sayHello}
{sayBye}
</div>
}
}
const sayHello = () => {
return 'Hello';
}
sayBye = () => {
return 'Hello';
}
This will return an exception: Uncaught ReferenceError: sayBye is not defined
Thanks a lot!
The answer is "it depends"... your two examples do very different things. Let's take a look at both before I give you a more detailed answer.
class ReactComp extend Component {
const sayHello = () => {
return 'Hello';
}
sayBye = () => {
return 'Hello';
}
render() {
<div>
{this.sayHello}
{this.sayBye}
</div>
}
}
The code above probably throws a syntax error as const (in this context) is not a valid decorator. Even if it was valid (or you simply omit it), sayHello() becomes a method on the ReactComp class (i.e. an instance method). Every time you create a new instance of this component, it will have an internal method called sayHello.
const example = <ReactComp />;
example.sayHello(); // oversimplified example
Make sense? On to your next example:
class ReactComp extend Component {
render() {
<div>
{sayHello}
{sayBye}
</div>
}
}
const sayHello = () => {
return 'Hello';
}
sayBye = () => {
return 'Hello';
}
Ignoring for a moment the syntax error you mentioned earlier, this code creates two global(ish) functions: sayHello() and sayBye() which (depending on your other code) could be accessed globally by any other component or script.
sayHello(); // I can run this line of code anywhere!
// no need for "const example = <ReactComp /> because sayHello() was defined outside of that class
My point: instance methods on a class are different than functions declared outside of a component.
Should one use const when declaring an arrow function in React class?
If you're creating an instance method, then no you don't need const. If you're creating a generic (i.e. utility) function outside of a component, then yes you probably should use const.
You can't define a variable using any declarative statement inside a class.
It expects property names to be attached to the this context of your class.
Defining the following class:
class C extends Component {
sayGoodBye = () => console.log("Bye!")
sayHello = who => console.log("Hello " + who)
render() {
this.sayGoodBye()
this.sayHello('world')
// ...
}
}
can be translated as:
const C = {
sayGoodBye : () => console.log('bye!'),
sayHello : who => console.log('Hello ' + who),
render : () => {
C.sayGoodBye()
C.sayHello('world')
}
}
if you try to define a variable inside a class using const/let/var it will result in an error.

Resources