Stateless function components cannot be given refs - javascript

I try to access some refs in my component. But I have this error in the console.
withRouter.js:44 Warning: Stateless function components cannot be given refs (See ref "pseudo" in FormInputText created by RegisterForm). Attempts to access this ref will fail.
Here is my component:
class RegisterForm extends React.Component {
render() {
return (
<form action="">
<FormInputText ref="pseudo" type="text" defaultValue="pseudo"/>
<input type="button" onClick={()=>console.log(this.refs);} value="REGISTER"/>
</form>
);
}
}
Plus when I click on the button I got Object {pseudo: null}in the console. I would expect an object instead null.
I am not sure to understand why this is not working. Note that my react tree uses mobx-react.

Refs do not work with stateless components. It is explained in the docs
Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component.
Stateless components at the moment of writing actually have instances (they are wrapped into classes internally) but you can not access them because React team is going to make optimizations in the future. See https://github.com/facebook/react/issues/4936#issuecomment-179909980

You could also try using recompose it has a function called toClass.
Takes a function component and wraps it in a class. This can be used as a fallback for libraries that need to add a ref to a component, like Relay.
If the base component is already a class, it returns the given component.

Related

How a component pass a prop to another component?

Newbie here, I am studying the documentation of react and in React Context API, I couldn't understand something, I won't understand the rest of the subject if I don't understand it. Can anyone help me what does it mean through using an example?
The Toolbar component must take an extra "theme" prop
and pass it to the ThemedButton. This can become painful
if every single button in the app needs to know the theme
because it would have to be passed through all components.
class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}
function Toolbar(props) {
// The Toolbar component must take an extra "theme" prop
// and pass it to the ThemedButton. This can become painful
// if every single button in the app needs to know the theme
// because it would have to be passed through all components.
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}
class ThemedButton extends React.Component {
render() {
return <Button theme={this.props.theme} />;
}
}
The Toolbar component must take an extra "theme" prop
this can be like <Toolbar theme="dark">
and pass it to the ThemedButton
how Toolbar component pass this prop to ThemedButton? and kindly clarify the rest of the comment as well.
Thank you for any help? You are kind
In your Toolbar component, it takes a parameter props, props is whatever properties have been passed to it when calling it, as in <Toolbar param1="someString" param2={someVariable}>, in this case the props value in Toolbar will be an object with the data you passed as key=value like for example: {param1: "someString", param2: content_of_someVariable}
And if you don't actually use those props (properties)/parameters in Toolbar, but rather in a subcomponent, then you have to pass them again to another level, like in <ThemedButton theme={props.theme} />, then ThemedButton itself finally passes the value to the component that actually makes use of, which is in your case: <Button theme={this.props.theme} />;.
So you had to pass the theme across multiple components, which don't use it or care at all about it, just to get it through to the final Button component.
(answer ends here, below is my effort to explain context API in an easy way)
To avoid that annoying level to level to another..., you can use the context API. Because it is really incontinent to pass a value across 3-4+ levels/components every time you want to use it in the last one in the chain.
Think about the context like a variable defined and exported on a root level and holds some data (like the user login status for example, or the theme infomation), and whenever you require that data, you import it and use it directly. You use the Provider property of the context you define (MyContext.Provider) to assign the data to it, and you use the Consumer property (MyContext.Consumer) to consume/access that data you assigned in the provider.
The beauty of the context consumer, is that whenever the data is updated in the provider, the consumer immediately gets the new data and triggers a re-render with the new data.
I hope I explained it in a simple and clear way. Write a comment with any questions or unclear parts and I can try my best to improve the answer.
Best of luck!
Props are properties that help define the way your JSX appears on the page.
When you use a component that you have created, you can pass it props like below:
<MyComponent myProp={myPropValue} />
You can continue to pass props down through the component hierarchy as well. So say you have a component tree like below:
MyComponent
--MySubComponent
----MySubSubComponent
You can pass props from MyComponent to MySubSubComponent like so:
<MyComponent myProps={MyProps} />
<MySubComponent mySubProps={props.myProps} /> //Props are the value you gave in the parent component
<MySubSubComponent mySubSubProps={props.mySubProps} />
Whatever title you give the props when declaring the component in JSX is the title you will call to get the value of the prop like props.myProps

In a react component class where exactly is the "props" object being pulled from?

To get straight to the point, in a react class based component where does the prop object come from?
I am following the official React tic-tac-toe game tutorial.
Firstly, when I take a look at the code for the react Component class (which we extend when creating a React component) I observe that the function has 3 parameters Component(props, context, updater) but I am puzzled as to why in the cases where super() is called only props is passed like so super(props).
Shouldn't there be values passed for context and updater also? Why is it that there are no errors when the code is run without super being called?
import React, { Component } from "react";
export class Square extends Component
{
render()
{
return (
<span>
<button className="square" onClick={ () => { alert("click") } }>
{this.props.value}
</button>
</span>
)
}
}
To be clear, I understand that the value property in {this.props.value} comes from the property passed to Square <Square value={index}/>; which is a child in another component (Board in the case of the React tutorial) but this is not what I'am referring to.
Props are the properties that are passed from the Super class to the class you create using extends Components in React.
Similar to what happens in OOPS where the parent class properties are passed to the children in the constructor . similar way the props are passed in React this applies in case of functional components too
Note - Please do not confuse it with OOPS concepts [ just to give a
Oversimplified version]
One thing is necessary: the parent's (which is Component class) constructor must be invoked within any React class component.
What super does (inside Square's constructor) is to invoke Component's constructor with Square's props. (Hope it's not complicated)
If Square has a constructor then you should call super implicitly.
If Square doesn't have a constructor, then Component's constructor will automatically be invoked when using <Square />.
Also you don't use context or updater directly in your components. So there is no need to define them there.

How can I ensure that React creates a new instance of a component, even if the component tree has not changed?

React updates its component tree based on the names of the elements in that tree.
For example:
<div>
<MyComponent/>
</div>
And:
<div>
<MyComponent enabled/>
</div>
...results in React using the same <MyComponent> instance (because the component name did not change). This is very useful because it ensures that internal state within the component instance persists.
See the documentation for more details.
My question: "Is there a way to force a new instance to be created in certain circumstances?"
So rather than using the same MyComponent instance, I would like a new one to be instantiated if (let's say) prop 'x' has changed.
Untested, but I think you could trick React and add the prop as a key on the component.
<div>
<MyComponent enabled key={enabled.toString()} />
</div>
Since you're familiar with the reconciliation docs, I imagine you know what keys do already ;)

Pure ReactJS Components

Dan Abramov says
...a component is pure if it is guaranteed to return the same result given the same props and state.
So if a component is supplied with the same props the same output will always be returned. This is clear.
He then says
pure components... don’t rely on deep mutations in props or
state, so their rendering performance can be optimized by a shallow
comparison in their shouldComponentUpdate() hook
But this means I could supply a pure component with the same props object, but with a difference located deeper inside said props object, and the component would render the same but for different (albeit a deep difference) props. This means this constraint is not enforced.
Is declaring a component as extends PureComponent really saying to ReactJS "I know what I am doing. I guarantee I am using immutable state. So you need only perform shallow props comparisons in shouldComponentUpdate"?
Finally, PureComponents provide a shallow shouldComponentUpdate method by default - presumably this can be overridden with whatever you want (even a deep comparison)?
Is declaring a component as extends PureComponent really saying to
ReactJS "I know what I am doing. I guarantee I am using immutable
state. So you need only perform shallow props comparisons in
shouldComponentUpdate"?
Yes
Finally, PureComponents provide a shallow shouldComponentUpdate method
by default - presumably this can be overridden with whatever you want
(even a deep comparison)?
You can override it. React will try to warn you not to do so. In this case its better to inherit from Component instead.
https://medium.com/groww-engineering/stateless-component-vs-pure-component-d2af88a1200b
class Welcome extends React.PureComponent {
render() {
return <h1>Welcome</h1>
}
}
Hello = () => {
return <h1>Hello</h1>;
}
So above there is an example of a very simple Welcome Pure Component
and Hello Stateless Component. When you use these two in your Parent
Component, you will see Hello will re-render whenever Parent Component
will re-render but Welcome Component will not
Also in cases where you want to use lifecycle methods of Component
then we have to use Pure Components as stateless components don't have
lifecycle methods.
Please read about Pure Render Checks
https://github.com/vasanthk/react-bits/blob/master/gotchas/01.pure-render-checks.md
and good articles there :
https://flexport.engineering/optimizing-react-rendering-part-1-9634469dca02
https://flexport.engineering/optimizing-react-rendering-part-2-7b2e9a9ea21f
https://flexport.engineering/ending-the-debate-on-inline-functions-in-react-8c03fabd144

What does "Stateless function components cannot be given refs" mean?

I have this:
const ProjectsSummaryLayout = ({projects}) => {
return (
<div className="projects-summary col-md-10">
<h3>Projects</h3>
<ul>
{ projects.map(p => <li key={p.id}>{p.contract.client}</li>) }
</ul>
</div>
)
}
const ProjectsSummary = connect(
state => ({projects: state.projects})
)(ProjectsSummaryLayout)
and I get:
Warning: Stateless function components cannot be given refs (See ref
"wrappedInstance" in ProjectsSummaryLayout created by
Connect(ProjectsSummaryLayout)). Attempts to access this ref will
fail.
What is it trying to tell me? Am I actually doing something wrong?
I see discussion about this here but unfortunately I simply don't understand the conclusion.
In React, refs may not be attached to a stateless component.
React Redux 3 attaches a ref to the component you give it regardless of whether or not it's stateless. The warning you see comes from React because internally, React Redux 3 attaches a ref to the stateless component you supplied (ProjectsSummaryLayout).
You're not doing anything wrong and according to this GitHub comment, you can safely ignore the warning.
In React Redux 4, no ref is attached to the wrapped component by default, which means if you upgrade to React Redux 4, the warning should go away.
React has 2 commonly used component styles.
Functional Component
Class Component
So, When I was making use of Functional one then I was encountering this error.
Code snippet corresponding to Functional Component
But as soon as I changed it to Class Component then it worked.
Code snippet corresponding to Class Component.
Try changing Functional Component to Class Component.
I hope it will resolve your problem.

Categories