Yesterday, I was reading the React documentation on higher order components and I was trying to use some of the examples that they have. But, for me, it isn't working.
Here is a simple HOC I created just to wrap another component and see how this works. But since the very beginning, it never worked.
import React, { Component } from 'react';
export default function (enhacedComponent) {
class Authenticate extends Component {
constructor(props) {
super(props);
}
render() {
return <enhacedComponent {...this.props} />;
}
}
return Authenticate;
}
It always returns me this error:
Warning: Unknown props `location`, `params`, `route`, `router`, `routeParams`, `routes` on <enhacedComponent> tag. Remove these props from the element.
When I check the HTML elements part in the console, I find that the actual value this HOC returns is <enhacedComponent></enhacedComponent>. So the wrapped component never got out!
So, in the end, the wrapped component never returns. Just a JSX version of what should be the argument of the HOC.
I think that since JSX is just a another syntax and the unique way to pass plain JavaScript is using {}, I tried to do this, to no success:
<{enhancedComponent} {...this.props }/>
I really don't know what to do or what I am doing wrong.
I'm using this HOC reference. I'm using Webpack 2 with webpack-dev-server as tools on Windows 10.
React thinks you're trying to pass these props to a DOM element and not a react component, which will give you the unknown props error. React interprets lower camel case as a DOM element, so enhacedComponent should be EnhacedComponent.
More info here:
https://facebook.github.io/react/warnings/unknown-prop.html
Related
When using React, what is the difference (and when should each method be applied) when rendering a component?
Does this impact the component lifecycle in any way? Or impact how hooks are run in the component?
Method 1:
class App extends React.Component {
...
function getComponent() {
return <Component />
}
render() {
return this.getComponent()
}
}
Method 2:
class App extends React.Component {
...
render() {
return <Component />
}
}
(Note: The OP has now changed the question, it used to have return {this.getComponent()} in Method 1.)
render in Method 1 is incorrect (well, it was before the edit), it should be:
render() {
return this.getComponent() // No {} wrapper
}
You need the {} within a JSX context, but you're not in a JSX context there. For instance, if you wanted to wrap what this.getComponent returned in a div, you'd use the JSX expression to define the div's children within the JSX defining the div:
render() {
return <div>{this.getComponent()}</div>
}
With the {} sorted out, whether you use Method 1 or Method 2 is up to you. If you have substantial parts of the render that you want to move into their own functions, that's fine. For instance:
render() {
return (
<div>
{this.getHeader()}
{this.getBody()}
{this.getFooter()}
</div>
);
}
...although I think I'd probably argue at that point that without a good counter-argument, the header, body, and footer should probably be components (perhaps function components). But the occasional helper function call like that is fine.
Does this impact the component lifecycle in anyway?
No. It's just a function call within render.
There is no real difference between both. I'd personally use only one render() method as much as possible, then when the method gets too big, extract parts of it into their own method.
I have found this great article by Kent C. Dodds. An extract of the article is:
React doesn't know the difference between us calling a function in our JSX and inlining it. So it cannot associate anything to the Counter function, because it's not being rendered like a component.
This is why you need to use JSX (or React.createElement) when rendering components rather than simply calling the function. That way, any hooks that are used can be registered with the instance of the component that React creates.
With this in mind, it sounds like it's better to use JSX when rendering a component that uses hooks.
I have started working on React recently and understood how refs can be used to get hold of a DOM node. In the React docs, they mention the two approaches of creating Refs. Can you please let me know in what situation a callback ref is better than createRef()? I find createRef to be simpler. Although the docs say "callback refs give you more fine grain control" I can't understand in what way.
Thank you
Besides what jmargolisvt said, one thing I found callback is very interesting that I can set multiple refs in an array so that I can control it better.
Like this:
class A extends React.Component {
constructor(props) {
super(props);
this.inputs = [];
}
render() {
return [0, 1, 2, 3].map((key, index) => (
<Input
key={key}
ref={input => this.inputs[index] = input}
/>)
);
}
}
createRef is returning either a DOM node or a mounted instance of a component, depending on where you call it. Either way, what you have in hand is indeed straightforward as you've noted. But what if you want to do something with that reference? What if you want to do it when the component mounts?
Ref callbacks are great for that because they are invoked before componentDidMount and componentDidUpdate. This is how you get more fine-grained control over the ref. You are now not just grabbing DOM elements imperatively, but instead dynamically updating the DOM in the React lifecycle, but with fine-grained access to your DOM via the ref API.
In terms of use cases, callback refs can do anything createRef can do, but not vice versa. createRef gives us a simplified syntax, but that's it.
Things you can't do with createRef:
React to a ref being set or cleared
Use an externally and internally provided ref on the same React element at the same time. (e.g. you need to measure a DOM element's clientHeight whilst, at the same time, allowing an externally provided ref (via forwardRef) to be attached to it.)
Practically you will see no difference except callback ref returns null before initial rendering.
This answer is a little biased on React-Native but still it is applicable if a React component similar to the following example.
<Animated.View> is a wrapper component for <View> that can be animated.
However if you want to access the <View> directly for something like calling the measure() method, then you can do it like:
interface State {
ref: View;
}
public render() {
<Animated.View ref={(component) => {
if (component !== null) {
this.state.ref = component.getNode();
}
}}
>
...
</Animated.View>
}
Otherwise, you need to do: this.state.ref.getNode().
TL;DR: you have control of what to do with an element or how to store it.
If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases.
I'm reviewing some code in a React-Redux codebase, and there are quite a few cases where a parent smart component is being passed as a prop to a child component:
import React from 'react';
import Child from '../components/Child';
export default class Parent extends React.Component {
constructor(props) {
super(props);
}
//...
render() {
return <Child parent={this}/>;
}
}
At initial glance, it appears that the intention here is to expose the props/state/methods of the parent to the child component. This sort of goes against many of the design patterns I've used in the past with React, but I'm not sure if it's something that is worth bringing up in a code review (it's already deployed to QA). It technically works (the child is able to call this.props.parent[method], etc) and significantly reduces the lines of code otherwise required if you pass individual handlers/slices of props/(local)state to the child. I know there are downsides (in one case, the parent property shared the same name as a reducer, so in the child component, it is unclear if this.props['reducerName'] is referring to a React Component or a mapped slice of state), but I can't be sure that the downsides are anything more than surface level.
Does something like this run the risk of unnecessary rerenders/diff checks in the child component? Does React ever need to recursively serialize components, and thus incur a lot of overhead because of circular references? Anything I can point out besides I don't think it looks right?
There are a few things I can think of why this might not be a good Idea:
This creates a very tight coupling between the parent and the component. Further, we should try to provide the minimum amount of data to the abstract modules. We call it Principle of least privilege. Here, a lot of information is being passed to the child component which will not be used and can even be abused using a lot of ways.
One case where it can be very bad idea is when the child component changes something on the date object: eg :
render() {
return (
<React.Fragment>
<ChildOne parent={this}/>;
<ChildTwo parent={this}/>;
</React.Fragment>
)
}
Now the ChildOne component can do something like :
this.props.parent.clickHandler = this.anotherHandler
This will break ChildTwo functionality.
First, some context.
I'm using Redux to manage authentication state of my app and have Auth as a Redux container (or smart component).
I've created a wrapper (a higher-order component) that takes Auth and returns it:
export default function AuthWrapper(WrappedComponent) {
class Auth extends Component {
... <Auth stuff here> ...
}
return connect(mapStateToProps, mapDispatchToProps)(Auth);
}
It seems to me that in order to use the wrapper, I just need to invoke it with a component I want to have behind my auth. For example, let's say I'm authenticating a component called UserPage with the wrapper, à la:
const AuthenticatedUserPage = AuthWappper(UserPage)
However, when I use the wrapper like this, React isn't happy with me. I get the following error:
Warning: AuthenticatedApp(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
My best guess is that it doesn't like the connect-ified component that Redux will create when I return it from AuthWrapper... which leads me to my question:
Does React support higher-order components when those components create Redux containers? And if so, why would React be throwing this error?
Here's my two cents. I think the error is occurring elsewhere.
According to this simplified version of the connect function in react-redux, the connect function is simply returning another react component. So in your case, you're returning a component, wrapped inside another component, which is still valid. A container is basically a component.
Read https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e for a better understanding of the connect function.
I also tried the following in my own application and it worked.
import Layout from '../components/Layout'
//Do some other imports and stuff
function wrapper(Layout) {
return connect(null, mapDispatchToProps)(Layout);
}
export default wrapper()
Like the error states, you might just simply be returning an invalid component somewhere in your app. Your app might be throwing the error because you're not wrapping a return call in parentheses on your render method.
Is it possible (or even a good idea) to add my own props to another React component, like:
<SomeCustomComponent myOwnParam={handler}>
As mentioned by Tyrsius, it really depends on the implementation of SomeCustomComponent. If the component does not use the myOwnParam prop anywhere, passing it won't accomplish anything. On the other hand, some React components might use JSX spread attributes to reference props not directly enumerated in the code.
As an example, the following implementation of SomeCustomComponent would pass your myOwnParam prop down to its child div:
class SomeCustomComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
var {customComponentProp, ...other } = this.props;
return (
<div customComponentProp={customComponentProp} {...other}></div>
);
}
}
So again, it depends on the implementation of SomeCustomComponent what will happen.
See Transferring Props documentation for more details: https://facebook.github.io/react/docs/transferring-props.html
This won't cause an error, but unless SomeCustomComponent is looking for this prop nothing will be done with it. It is possible for a component to loop over its props, so this could be a usable strategy, but I am not sure what you would do with it. You couldn't define anything but iteration logic over properties that you don't know in advance.