After starting to work with React.js, it seems like props
are intended to be static (passed in from the parent component), while state
changes based upon events. However, I noticed in the docs a reference to componentWillReceiveProps
, which specifically includes this example:
componentWillReceiveProps: function(nextProps) {
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}
This seems to imply that the properties CAN change on a component based upon the comparison of nextProps
to this.props
. What am I missing? How do props change, or am I mistaken about where this gets called?
asked Jul 24, 2014 at 16:50
Matt HugginsMatt Huggins
80.3k36 gold badges147 silver badges217 bronze badges
A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.
For instance, a Dashboard has a speed
field in its state, and passes it to a Gauge child thats displays this speed. Its render
method is just return <Gauge speed={this.state.speed} />
. When the Dashboard calls this.setState({speed: this.state.speed + 1})
, the Gauge is re-rendered with the new value for speed
.
Just before this happens, Gauge’s componentWillReceiveProps
is called, so that the Gauge has a chance to compare the new value to the old one.
jasonmerino
3,2101 gold badge20 silver badges38 bronze badges
answered Jul 24, 2014 at 20:52
10
PROPS
A React component should use props to store information that can be
changed, but can only be changed by a different component.
STATE
A React component should use state to store information that the
component itself can change.
A good example is already provided by Valéry.
answered Jul 25, 2018 at 18:14
Ali AdraviAli Adravi
21k9 gold badges83 silver badges83 bronze badges
3
Props can change when a component’s parent renders the component again with different properties. I think this is mostly an optimization so that no new component needs to be instantiated.
answered Jul 24, 2014 at 18:02
Joost DiepenmaatJoost Diepenmaat
17.6k3 gold badges43 silver badges53 bronze badges
Trick to update props if they are array :
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button
} from 'react-native';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: this.props.count
}
}
increment(){
console.log("this.props.count");
console.log(this.props.count);
let count = this.state.count
count.push("new element");
this.setState({ count: count})
}
render() {
return (
<View style={styles.container}>
<Text>{ this.state.count.length }</Text>
<Button
onPress={this.increment.bind(this)}
title={ "Increase" }
/>
</View>
);
}
}
Counter.defaultProps = {
count: []
}
export default Counter
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
BenMorel
33.5k49 gold badges174 silver badges310 bronze badges
answered Jun 26, 2017 at 15:47
Abhishek KumarAbhishek Kumar
2,0463 gold badges24 silver badges35 bronze badges
1
If you use recompose
, use mapProps
to make new props derived from incoming props
Example:
import { compose, mapProps } from 'recompose';
const SomeComponent = ({ url, onComplete }) => (
{url ? (
<View />
) : null}
)
export default compose(
mapProps(({ url, storeUrl, history, ...props }) => ({
...props,
onClose: () => {
history.goBack();
},
url: url || storeUrl,
})),
)(SomeComponent);
answered Oct 3, 2018 at 17:35
ehacinomehacinom
7,4107 gold badges40 silver badges63 bronze badges
0
Последнее обновление: 01.04.2022
Props представляет коллекцию значений, которые ассоциированы с компонентом. Эти значения позволяют создавать динамические компоненты, которые
не зависят от жестко закодированных статических данных.
Функциональный подход:
function Hello(props) { return <div> <p>Имя: {props.name}</p> <p>Возраст: {props.age}</p> </div>; }
Параметр props, который передается в функцию компонента, инкапсулирует свойства объекта. В частности, свойство name
и age
.
При рендеринге мы можем создать набор компонентов Hello, но передать в них разные данные для name и age. И таким образом, получим набор однотипной
разметки html, наполненной разными данными.
Использование классов:
class Hello extends React.Component { render() { return <div> <p>Имя: {this.props.name}</p> <p>Возраст: {this.props.age}</p> </div>; } }
Класс компонента также извне получает объект свойств, который доступен через this.props
.
Использование стрелочных функций (arrow functions):
const Hello = (props) => { const {name, age} = props; return(<div> <p>Имя: {name}</p> <p>Возраст: {age}</p> </div>); }
Используем компонент Hello:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <div id="app"></div> <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <script type="text/babel"> function Hello(props) { return <div> <p>Имя: {props.name}</p> <p>Возраст: {props.age}</p> </div>; } ReactDOM.createRoot( document.getElementById("app") ) .render( <Hello name="Tom" age="33" /> ); </script> </body> </html>
При рендеринге React передает значения атрибутов в виде единого объекта «props». То есть значение из атрибута
name="Tom"
перейдет в свойство props.name
.
В итоге будет создана следующая страница:
Значения по умолчанию
Мы можем определить для свойств значения по умолчанию на тот случай, если их значения не передаются извне.
Если мы применяем классы, то для установки значений применяется статическое свойство defaultProps:
class Hello extends React.Component { render() { return <div> <p>Имя: {this.props.name}</p> <p>Возраст: {this.props.age}</p> </div>; } } Hello.defaultProps = {name: "Tom", age: 22};
При функциональном определении компонента также применяется свойство defaultProps
:
function Hello(props) { return <div> <p>Имя: {props.name}</p> <p>Возраст: {props.age}</p> </div>; } Hello.defaultProps = {name: "Tom", age: 22};
И в любом из этих случаев, если мы не определим какие-то свойства для компонента, то они будут брать значения из значений по умолчанию:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <div id="app"></div> <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <script type="text/babel"> function Hello(props) { return <div> <p>Имя: {props.name}</p> <p>Возраст: {props.age}</p> </div>; } Hello.defaultProps = {name: "Tom", age: 22}; ReactDOM.createRoot( document.getElementById("app") ) .render( <Hello name="Bob" /> ); </script> </body> </html>
Обновление props
Сам this.props представляет неизменяемый объект, который предназначен только для чтения. Поэтому не следует его изменять, например:
class Hello extends React.Component { render() { this.props.name = "Tom"; return <h1>Привет, {this.props.name}</h1>; } }
Если же надо время то времени изменять какие-то внутренние данные компонента, то для хранения таких данных в React предназначен объект state,
который будет рассмотрен в следующей статье.
by Dheeraj DeeKay
If you have read the official React docs (and you should, as it is one great resource on React) you’d notice these lines:
Whether you declare a component as a function or a class, it must never modify its own props.
React is pretty flexible but it has a single strict rule:
All React components must act like pure functions with respect to their props.
Props are never to be updated. We are to use them as is. Sounds rigid right? But React has its reasons behind this rule and I’m pretty convinced by their reasoning. The only caveat is, though, that there are situations where we might need to initiate the update of a prop. And we will soon know how.
Consider the following line of code from a parent component:
<MyChild childName={this.state.parentName}
/>
This is a simple line which every React dev is probably familiar with. You are calling child component. While you are doing that, you are also passing the state of the parent (parentName
) to the child. In the child component, this state will be accessed as this.props.childName.
Fair enough.
Now if there is any change of name required, parentName
will be changed in the parent and that change will automatically be communicated to the child as is the case with the React mechanism. This setup works in most of the scenarios.
But what if you need to update the prop of the child component, and the knowledge of the change required and the trigger to change it is only known to the child? Considering the ways of React, data can only flow from top-to-bottom i.e., from parent-to-child. So then how are we to communicate to the parent that a change to prop is required?
Well, although this is anti-pattern and not recommended, the devs who wrote the language have us covered. Surprise!
We can do it with Callbacks. I know, no surprise there! They seem to come in handy for every problem we face here. Okay, okay, now how?
Imagine if the above call to the child was modified this way:
<MyChild childName={this.state.parentName} onNameChange={this.onChange}
/>
Now in addition to a prop childName
our needy-child also has an event called onNameChange
exposed. This is the way to resolve the issue. Our child has done its part. Now it’s the parent’s turn to do what is required. And it need not fret. All it needs to do is define a function onChange
as
function onChange(newName) { this.setState({ parentName: newName });}
That’s it. Now whenever and wherever in the child component we wish to update the parentName
prop, all we have to do is call `this.props.onNameChange(' My New name')
and voilà! You’ll have what you desire. That’s it. Done and dusted.
Hope that was easy to grasp. Let me know in the comments about any difficulties or different ways in which it could have been made easier. Thanks.
One last thing.
React argues against this and they are pretty right about it. This is anti-pattern. So whenever you run into a situation like this, check to see if you could lift your state up or if there is any way you could break your component down. It might sound a wee bit tedious, but know that that’s the way it is supposed to be in React!
Happy Coding.
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started