ReactJS: adding my own props to another component - javascript

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.

Related

Rendering a component in JSX vs via function

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.

Storing methods needed in all components

I have a universal app I'm developing for learning purposes. I'm managing the state of my app with Redux, so all my data will be available there. But I want to create some methods that I'm going to use in all my components. The problem is: where should I store this methods?
Adding them to a parent component and passing the methods as props doesn't seem very useful, because this is one of the things that Redux tries to solve. And I'm pretty sure that Redux is not a place for storing methods.
I know I can create a class in a file somewhere, export it, add some methods to it, and when I want to use one method in a component I can call this file, create an instance of the class and call the needed method; but this doesn't look very react to me…
Is there a right way to create methods available for all components?
I've had some success sharing functions between components using an approach similar to the following. I'm not sure this approach will solve your specific use case with regards to cookies, however.
These functions can be stored anywhere and imported wherever required. They accept a component as their first argument, then return a function that operates on the component passed in.
Indicative, untested code follows.
// An event handler than can be shared between multiple components
const handleChange = component => event => component.setState({ value: event.target.value });
class ComponentOne extends PureComponent {
state = {};
render() {
return (
<div>
{this.state.value}
<input onChange={handleChange(this)} />
</div>
);
}
}
class ComponentTwo extends PureComponent {
state = {};
render() {
return (
<div>
{this.state.value}
<input onChange={handleChange(this)} />
</div>
);
}
}

Passing props to a component through state

Prefix:
I am working with react-native, and am wondering the best practice for passing props down from a parent to a child component. I have tested this on my android device only.
Question:
From my understanding it is possible to pass values to a component through the use of props, ie:
<myComponent myProp="some data" />
and it can be referenced in my myComponent using this.props.myProp. Would it be bad practice (or will it even work) to create my state object in the constructor like so:
constructor(props){
super(props);
this.state = {
myStateProp: this.props.myProp
};
}
which could then be called in that component as this.state.myStateProp. I am relatively new to react-native and am trying to learn as much as I can. I have tried it in several use cases with varying results, and am uncertain as to the behavior. Thank you for your input!
There are few good reasons to do this. It's generally considered an anti-pattern because components should be stateless wherever possible.
If what you're trying to do is control the component by passing in props and using as state, I would suggest holding the state in the parent component and then passing any changes back up the chain via props, using a callback.
For example
ComponentOne {
this.state = { colour:red }
handleColourChange(val){
this.setState({ colour: val })
}
return <ComponentTwo changeColour={this.handleColourChange} colour={this.state.colour} />
}
Then imagine in ComponentTwo we have a button and you want to change colour:
<button onClick={this.changeColour(blue)}>Change to blue</button>
This way your child component remains stateless, and is controlled by its parent. this.props.colour will change in the child automatically.

Adding props to constructor as this.prop

I have a number of methods in a React class component. The component itself receives a number of props.
I am wondering if I should take the props and add each of them as this.propName in the constructor and then access the props using this.propName. Here is an example. What is best practice?
const classComponent = class classComponent extends Component {
constructor(props) {
super(props)
this.propA = props.propA
this.propB = props.propB
}
methodA() {
console.log(this.propA)
}
}
Alternative
const classComponent = class classComponent extends Component {
constructor(props) {
super(props)
}
methodA() {
console.log(this.props.propA)
}
}
Official documentation of React.js in State and Lifecycle section says:
While this.props is set up by React itself and this.state has a special meaning, you are free to add additional fields to the class manually if you need to store something that is not used for the visual output.
In your case, most likely it should stay as a prop. Whenever you pass anything as a parameter, which in React.js philosophy would be a prop, it's most likely an ingredient of the visual effect.
Once you create a variable it uses memory and, even if you are referencing a type, like an array or an object, you make your file bigger. Creating new names for variables already accessible to your class/function make no sense, so don't do it.
The way you handled the props does not allow the component to update when it receives new props; mainly because constructor is only called once--at the creation of the component.
A better way to do it is to use Destructuring assignment in the render function:
render() {
{propA, propB, ...rest} = this.props;
//Rest code here, using propA, propB
//However, don't use this.propA, or this.propB
}
If you still like to do the way you want to do, you have to add the following function inside your component, to make your component update whenever it receives new props:
componentWillReceiveProps(nextProps) {
this.propA = nextProps.propA;
this.propB = nextProps.propB;
}
As you can see, unnecessary code had to be included, so I think this is a wrong way to do it!

When should a react component be declared as a function, and not a class?

I'm unsure of when to declare react components as simple standalone functions as opposed to the regular class myComponent extends Component syntax. To use an example from React's docs (located here):
The following is referred to as a "component"
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
While it appears to merely be a function and is declared like any regular old function. Then in the next paragraph, the following is ALSO defined as a component, and looks more like the way I think a component should look:
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {temperature: ''};
}
handleChange(e) {
this.setState({temperature: e.target.value});
}
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input
value={temperature}
onChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
What is the difference between these two "components"? Is the first example actually a component if it doesn't inherit from the Component class and isn't being created with React.createClass? I would appreciate somebody explaining this distinction since I couldn't find an answer anywhere in the docs.
When you don't need to use the lifecycle methods and the component isn't stateful you can declare the component as a function. Component lifecycle methods like componentWillMount() and componentDidMount() only can be used if the component is a class that extends Component.
Calculator must be specified as a class-based component because it is dependent upon internal component state i.e. this.setState({...}). Functional components, also known as stateless components do not have a backing instance, thus they are unable to maintain local state in the same way.
Personally, I always try to write functional components as they are arguably easier to test due to their nature of consuming props and returning a tree of ReactElement instances. I will only convert a component to be class-based if it will:
need to manage its own presentation-based state i.e. not applicable to the state of the entire application
benefit from lifecycle methods as a means of improving performance through restricted re-rendering
require references to child ReactElements or DOM nodes via refs
There are two complementary docs from Facebook that explain this quite well:
https://facebook.github.io/react/docs/components-and-props.html
https://facebook.github.io/react/docs/state-and-lifecycle.html
TL;DR a "component" is primarily responsible for representing some DOM. Depending on how your application is organized, your component may or may not need to maintain its own state or have access to the lifecycle methods like componentDidMount or render. In the case that you do need these features, your component should be a class that inherits from React.Component. Otherwise, you can likely get away with writing your component as a plain old function.
If the functional way is more preferred instead of creating classes you could use higher-order components utility called recompose, it has lifecycle HOC.
Small example:
const NewComponent = lifecycle({
componentWillMount() {
this.props.onEnterScreen();
},
})(Component)

Categories

Resources