I have an element with a ref that is defined and ends up getting rendered into the page :
<div ref="russian" ...>
...
</div>
I want to access the DOM element properties like offset... or something. However, I keep getting undefined and I haven't the faintest idea why. After some searching it's clear that refs are only applicable to one file but I'm not using this anywhere besides this one page. I'm saying this to log it:
console.log('REFS', this.refs.russian);
What could be causing this?
Check that you are not accessing ref before the child component has been mounted. E.g. it doesn't work in componentWillMount. A different pattern which auto invokes ref related callback after the element has been mounted is this-
<div ref={(elem)=>(console.log(elem))}/>
You can use this notation to get mounted elements in deep nesting as well -
<div ref={this.props.onMounted}/>
The correct place to work with refs is inside specific React lifecycle methods e.g. ComponentDidMount, ComponentDidUpdate
You cannot reference refs from the render() method. Read more about the cautions of working with refs here.
If you move your console.log('REFS', this.refs.russian); call to ComponentDidMount or ComponentDidUpdate lifecycle methods (assuming you are on React >= 14) you should not get undefined as a result.
UPDATE: also refs will not work on stateless components per the caution link above
Update since React version 16.4
In your constructor method define your ref like this
constructor(props) {
super(props);
this.russian = React.createRef();
}
In your render where you are using ref do this.
<input
name="russian"
ref={this.russian} // Proper way to assign ref in react ver 16.4
/>
For e.g if you want to have focus when component mounts do this
componentDidMount() {
console.log(this.russian);
this.russian.current.focus();
}
Reference Refs Documentation React
I was having a similar issue in my form validation methods, trying to assign this.ref.current.reportValidity()
Writing the method I was doing this in as validate = () => {} instead of validate() {} helped me out, but I'm not totally sure why exactly, just something I remembered from habits I had in my past work experience that gave me this. Hope it helps and could someone kindly clarify this answer with why this might work exactly.
If you are exporting class withStyle, please remove and export default nomally.
Instead of putting your Console.log inside the function example(){...} you should put it inside:
example=()=>{....}
Related
I’m calling a function that returns some html code.
But if I want to send this function a parameter, then it tells me that Functions are not valid as a React child, the problem is that I want to access the props from the function, in order to do that, I changed the call in jsx as:
... ...
{this.showActivitiesIcon.bind(this)}
... ...
I tried setting a state inside the component, and setting the state from componentDidMount
componentDidMount = () => {
this.setState({
currentCountry: this.props.country
})
}
But, inside componentDidMount, there’s no such thing as this.props.country, and it’s useless to set this.componentDidMount.bind(this) inside the constructor. What can I do to fix it?
Here is the correct syntax, because bind(thisArg) returns a function:
{this.showActivitiesIcon.bind(this)()}
You seem like something:
super(props)
Can you share the whole code for this component?
Seems like you're are not calling the function in your JSX.
Make sure you invoke it while using it so that it returns valid JSX.
this.showActivitiesIcon.bind(this)()
From React documentation.
Conceptually, components are like JavaScript functions. They accept
arbitrary inputs (called “props”) and return React elements describing
what should appear on the screen.
Considering:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
or
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Will give us the ability to do this:
<Welcome name="Luke" />;
<Welcome name="Leia" />;
to use as we wish in the DOM,
Hello, Luke
Hello, Leia
Now when people prescribe props shouldn't be changed, it would make sense the reason is in my thinking would be like the same as changing the values of attributes of an image tag?
HTML:
<img id="Executor" alt="Picture of Executor" src="/somepath/vaders-star-destroyer-executor.jpg"/>
JS:
Meanwhile in a Javascript file a long time ago in a galaxy far, far away...
var imageOfVadersStarDestroyer = document.getElementById('Executor');
imageOfVadersStarDestroyer.src = "/somepath/vaders-star-destroyer-avenger.jpg"
Because if we keeping changing an elements attribute values this can cause confusion and slower renderings?
So is the reason why the prescription is to never change props in React is because is the library is trying to make elements as predictable as possible?
Setting props outside of React is dangerous and should be avoided. Why? The main reason is that it doesn't trigger re-renders. Hence bugs and unexpected behaviour.
Re-rendering
Most of the time, props are data that is store as state in the parent component, which is manipulated by calling setState() (or the second function returned by React.useState()). Once setState() is called, React re-renders and computes what has changed under the hood, with the latest props and state. Manually assigning values to props, therefore won't notify React that the data has changed and something has to be re-rendered.
The good practice
Making props read-only allows React components to be as pure as possible, which is obviously a good practice anyway even when writing plain JS. Data won't be changed unexpectedly and can only be done so by calling setState() (You might have heard of the single source of truth, which is what React is trying to leverage).
Imagine you notice something went wrong in the app and the data shown to the end user is completely different from the source, it would be a pain trying to find out where the data has been manipulated wouldn't it? :)
never change props in React
means that you should never do this.props.name = "userName" because of React's one way data binding, props are read only, to update a component's props, you should pass a function from the parent that will do that ( in the parent ) , or dispatch an action if you're using redux, a change in the props will trigger a re-render
props is a constant in this case. You will always need it in your components.
But there is a cleaner way to write it or even omit it.
Regular way with Function Expression (same as your exemple)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
ES6 Object Destructing - explicit
function Welcome(props) {
const {name} = pros
return <h1>Hello, {name}</h1>;
}
ES6 Object Destructing - inplicit, cleaner way
function Welcome({name}) {
return <h1>Hello, {name}</h1>;
}
And of course, you can use the class way which requires the usage of this.props.yourAttr
However, in the new version 3 of create-react-app, changed class components to functional components. You can see this exact modification on Github here.
You can need to learn more about destructing assignment in the old and good MDN linked here or an in-depth approach both array and object destructuring here.
I have been working with Redux & React for a few months. I usually always use Chrome with no issues. ( Endless bugs actually :) ).
When I started testing in Firefox I ran into an issue which I need some help with ... To know if there is a perfect way at dealing with this ...
Issue
Redux Props for MapStateToProps are not yet available when the constructor gets called, which means I cannot construct my components state in the component constructor. These props become available swiftly afterwards in the render function. At this stage, it is too late because I cannot construct state in the render function (Could somehow work that, but wouldn't be good to approach right ?).
For the moment I am using the componentWillReceiveProps and duplicating my constructor function with one exception
Constructor function
constructor(props){
super(props);
//Loads of code named A
this.state = {state:A};
}
Component Will Receive Props Function
componentWillReceiveProps (){
//Loads of code named A
this.setState({state:A});
}
There may be an issue over overwriting my state here, but for my exact case here, its only displaying data, no UI changes happen... This doesn't appear correct method either way...
I read this article
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
I am not quite sure if I understand this fully. I did experiment with it a little with no working solutions.
Ideally, I need the constructor to pause until all redux store is populated which also doesn't make sense. Props arrays could be empty.
There are discussions on Slack but none seem to address this exactly. I tried googling issue but couldn't find exact issue addressed ...
I need the mapStateToProps props to construct my state. It is looking like I won't be able to do this and will need to totally refactor code to work more solely in the render function with loads of ternary operators and/or making calls to set state from the render function before the render returns.
Any thoughts on this issue?
Daniel
Why do you think you need put the data you get from props into the component state?
As far as using the data there is no difference between the two except that you're more likely to get into trouble if you copy props to state (see link you posted).
const { A } = this.state;
const { A } = this.props;
If the data is coming via an async method then you should accommodate that in your render method.
render() {
const { A } = this.props;
if (!A) {
return <LoadingIndicator />
}
...
}
I am learning React via an online course and have stumbled across a situation where a property is attached to another property like so:
this.props.property01(this.props.property02)
Seeing as the tutor only briefly addresses this line of code I cannot but remain baffled as to what this "concatenation" syntax actually stands for, i.e. what it causes behind the scenes. Coming from Vanilla JS it looks like property02 is being used as an argument for property01 but that seems too simple an answer. That being said, I understand the remaining code quite well.
To provide some context I have created this codepen in which the problem I refer to above is given by this.props.onDelete(this.props.whichItem);.
Seeing as I could not find any related questions, I would be grateful for some insightful elaboration on this one.
The properties of a React component can be functions. When I see:
this.props.property01(this.props.property02)
I think that:
this.props.property01 is a function.
this.props.property02 is passed to the function as an argument.
This means that the component would be used as:
<SomeComponent property01={(a) => { /* so something with "a" ... */ } property02={"someValue"} />
If property02 is only used to be passed to property01 and nothing else I would prefer something like:
<SomeComponent property01={(a) => { /* do something with "someValue" ... */ } />
Which means that there is no need for a property called poperty02.
Coming from Vanilla JS it looks like property02 is being used as an argument for property01
That's it, you are correct.
this.props.property01(this.props.property02)
property01 is a method, property02, the argument.
A more elaborated explanation for anyone else looking at this:
Assume this line is in a component called MyComponent and property01 is a prop in MyComponent.
The parent component's render() method, would contain something like this:
<MyComponent property01={this.someMethod.bind(this)} />
Where someMethod belongs to that parent component but it becomes available as property01 in MyComponent (the child component).
If you can understand the basic react code this question will help you because in that code I passed props and state from parent component to the child component. You can play with it try to do whatever you want.
How to pass state from parent compont to child component in route (react-route-dom) reactjs
I am currently using strings for ref= in React 15.3.2, and such is deprecated.
So if I use a callback per the docs:
ref={(input) => this.textInput = input}
Then this will attach a DOM Element to my class when the component mounts.
Yay! A DOM element. So now I do not have to do:
ReactDOM.findDOMNode(this.refs.input).value=''; // uncontrolled component
I thought the whole idea of react is to not touch the DOM...
Lets assume I have a TextInput component that is complex, and has an InputError component along with <input type="text" -- this TextInput component does a bit of validation based on props, and it has a state that helps things like when to show error.
Back up in the form, I want to clear the form, so TextInput has a .clear() which resets its state. (Am I doing it wrong already?)
The thing is, I cannot access any child components React Objects unless I use strings as ref=, so I cannot call clear().
What gives?
Am I supposed to route "all communication" through props? What good is this.refs once all refs are callbacks? Can I get my react objects through .children or something? What is the convention on this issue?
Edit:
Obviously I am learning React, I guess the basic question is, is it bad (anti-react) to EVER call methods on a child component?
The components in question can be found here:
RegisterForm.jsx
TextInput.jsx
InputError.jsx
The requirement I find difficult/strange making work via props is TextInput: "onblur then if error then show error, mark as errored until changing passes validate"