I'd like to create 2 react components <Father /> and <Child /> and force the developer to use Child only inside Father:
<Father>
<!-- should be fine -->
<Child />
</Father>
<!-- should throw an error -->
<Child />
Is there any way to do it? If so, what's the syntax I should use?
You can leverage the context API to determine whether a child has a Father in parent or not.
The way you can do that is for your Father component to render a ContextProvider and your child to use the context
const FatherContext = React.createContext(null); // default value used if father not in hierarchy
const Father = ({children}) => {
// Component Logic here
return (
<FatherContext.Provider value={"Father"}>
{/* rest content */
{children}
</FatherContext.Provider>
)
}
and your Child can be like
const Child = () => {
const context = useContext(FatherContext);
if(context == null) {
console.warn("Child must be rendered inside of Father component"); // You can throw an error here too
}
return (...)
}
Now depending on which version of React you use, the implementation of Context differs but the idea remains the same
You can do something out of the box like this:
<Father>
{React.cloneElement(this.props.children, {...this.props, dna: 'uniquefather'})}
</Father>
Child class
...
if (this.props.dna !== 'uniquefather') throw new Error('something');
Here, the father will be passing an unique identifier, which if not received will throw error in child class.
I want to insert some props to a React component which I have extracted out of props.children, like so:
<PageContainer>
<PageOne />
<PageTwo />
<PageThree />
</PageContainer>
Inside <PageContainer> i am extracting the current page via props.children and current page index, something like this:
const { children, pageIndex } = props;
let activePage = React.Children.toArray(children)[pageIndex];
Inside this PageContainer I have the "oportunity" to send down a function that I need inside the <PageOne>, <PageTwo> and <PageThree>. I tried something like this, but then I got some compiling problems, I think. Since this worked locally and not in my test environment:
const newProps = React.cloneElement(activePage.props.children, { myWantedFunction: myWantedFunctionThatIsAvailableInsidePageContainer });
activePage = React.cloneElement(activePage, { children: newProps });
The problem here is that myWantedFunction is not working in the test environment, but it is working locally. It says that it is not a function in the test environment, but when I console.log it out locally, it prints out a function. I am guessing there is a compiling problem, but I am wondering if there is a better way to acheive this (send down props to a component stored in a variable that I got out of props.children)?
Thank you in advance!
You are almost correct, you need to use React.cloneElement() to send props down to the child component. First you need to get the active page which you're doing right:
let activePage = React.Children.toArray(children)[pageIndex];
Then you need to use React.cloneElement to pass props to this component like this. Let's the name of the prop is isAuthenticated which is a boolean:
let component = React.cloneElement(activePage, { isAuthenticated: true })
Now in your page you'll be able to access this prop: prop.isAuthenticated
I created a working demo for you, have a look:
https://codesandbox.io/s/determined-kowalevski-eh0ic?file=/src/App.js
Hope this helps :)
Alternatively you could also do something like this:
const PAGES = [PageOne, PageTwo, PageThree]
function PageContainer(props){
const {pageIndex} = props
const ActivePage = PAGES[pageIndex]
return <ActivePage someFunction={someFunction} />
function someFunction(){
// the function you want to pass to the active page
}
}
Node that ActivePage has a capital A, which allows it to be used as a JSX component.
A drawback of this solution is however that if you use typescript it wont type check the props correctly since you only know which component is to be rendered at runtime. You could replace the array lookup with a switch to avoid that issue.
Yet another variation would be to just let the Page components handle their own state and pass the function to all of them. Like this:
function PageContainer(props){
const {pageIndex} = props
const someFn = () => 0
return <React.Fragment>
<PageOne id={1} activePage={pageIndex} someFunction={someFn} />
<PageTwo id={2} activePage={pageIndex} someFunction={someFn} />
<PageThree id={3} activePage={pageIndex} someFunction={someFn} />
</React.Fragment>
}
then in the Page Components just check if the pageIndex corresponds to their id:
function PageOne(props){
const {id, activePage, someFunction} = props
if (id === activePage){
const result = someFunction()
return <div>Page One: {result}</div>
}
}
I want to apply different style for selected element from a long list.
I'm passing to React component element as props: currentId and selectedId.
Inside render function, I compare both ids and apply proper styles.
When clicking any element from the list, I fire an action with the new selected Id and all elements in the list will re-render(because selectedId prop does change).
If the list has 1000 element and I click one of them, It would be nice to only update 2 elements (new selected and deselected ones) not all of them.
Is these a better way to handle this scenario in React?
Update: Add code example
List component:
const MyList = (props) => {
const items = props.items;
const selectedId = props.selectedId;
return (
<div>
{items.map((item) => (
<MyItem
currentId={item.id}
selectedId={selectedId}
key={item.id}
content={props.content}
/>
))}
</div>
);
};
Item component:
const MyItem = (props) => {
const isSelected = props.currentId === props.selectedId;
return (
<div className={isSelected ? 'selected-item' : ''}>
<h1>{props.currentId}</h1>
</div>
);
};
You can implement shouldComponentUpdate logic to prevent components from rerendering. Generally this is a bad idea (more on that later) but it does seem to apply to your use case. In general it is better to simply use PureComponent to prevent unneeded rerenders. This implements shouldComponentUpdate logic that compares state and props and if neither has changed, no update occurs.
Without seeing your code this is my best guess as to what shouldComponentUpdate might look like in your context:
shouldComponentUpdate(nextProps) {
if(this.state.isSelected && this.state.id !== nextProps.selectedId) {
return true;
} else if (!this.state.isSelected && this.state.id === nextProps.selectedId) {
return true;
}
return false;
}
Note that this means that a rerender will not happen unless shouldComponentUpdate returns true or you call this.forceUpdate() on that component. Your component won't even render if this.setState() is called, unless you add in more specific logic so that shouldComponentUpdate returns true on state changes. This can lead to difficult to debug problems, where your UI fails to reflect changes in application state but no obvious error occurs. This behavior doesn't apply to child components, so if these components have children they will still rerender as expected. If you decide to implement shouldComponentUpdate, you can add logic to compare state as well by declaring the nextState parameter:
shouldComponentUpdate(nextProps, nextState) {
if(this.state.isSelected && this.state.id !== nextProps.selectedId) {
return true;
} else if (!this.state.isSelected && this.state.id === nextProps.selectedId) {
return true;
} else if (/*compare this.state to nextState */) { .... }
return false;
}
Implementing your own shouldComponentUpdate is tricky, and may require you to restructure your code for best results (for example, passing an isSelected variable to your components instead of allowing those components to decide whether or not they are selected might allow you to easily implement PureComponent). Best of luck!
I'm working on a React App using Flux - the purpose of which is a standard shopping cart form.
The trouble I'm having is with mapping over some data, and rendering a child component for each iteration which needs local state in order to handle form data before submitting, as I'm getting conflicting props from within different functions.
The following component is the HTML table which contains a list of all products.
/*ProductList*/
export default React.createClass({
getProductForms: function(product, index) {
return (
<ProductForm
product={product}
key={index}
/>
)
},
render: function() {
var productForms;
/*this is set from a parent component, which grabs data from the ProductStore*/
if(this.state.products) {
productForms = this.state.products.map( this.getProductForms );
}
return (
<div className="product-forms-outer">
{productForms}
</div>
);
}
});
However, each child component has a form, and if I understand correctly, the form values should be controlled by local state (?). The Render method always gets the expects props values, but I want to setState from props, so I can both pass initial values (from the store) and maintain control of form values.
However, componentDidMount() props always just returns the last iterated child. I've also tried componentWillReceiveProps() and componentWillMount() to the same effect.
/*ProductForm*/
export default React.createClass({
componentDidMount: function() {
/*this.props: product-three, product-three, product-three*/
},
render: function() {
/* this.props: product-one, product-two, product-three */
<div className="product-form">
<form>
/* correct title */
<h4>{this.props.productTitle}</h4>
/* This needs to be state though */
<input
value={this.state.quantity}
onChange={this.handleQuantityChange}
className="product-quantity"
/>
</form>
</div>
}
});
Let me know if there's any more details that I can provide to make things more clear - I've removed other elements for simplicity's sake.
Thanks in advance!
this is strange. Alternatively, you can set your state in the constructor to empty values for every field e.g
constructor(props) {
super(props);
this.state = {quantity: ''};
}
and then in your render function do smthg like:
render: function() {
let compQuantity = this.state.quantity || this.props.quantity;
/* this.props: product-one, product-two, product-three */
<div className="product-form">
<form>
/* correct title */
<h4>{this.props.productTitle}</h4>
/* This needs to be state though */
<input
value={compQuantity}
onChange={this.handleQuantityChange}
className="product-quantity"
/>
</form>
</div>
}
This way on the first render it'll use whatever is passed in the props and when you change the value, the handleQuantityChange function will set the state to the new value and compQuantity will then take its value from state.
So I've figured out what the issue was. I wasn't using the key within the getProductForms method properly. I was debugging and just output the index in each form - it was always 0, 1, 2, 3... (obviously). So I looked into how those were relevant to the state for each one.
Given that the order of the array I was using (most recent first), the first iteration always had an index and key of 0, even though it was the newest item. So React probably just assumed the '0' item was meant to be the same from the beginning. I know there's a lot of nuances of react that I don't totally understand, but I think this proves that the state of a looped component is directly associated with it's key.
All I had to do was to use a different value as a key - which was a unique ID I have with each product, and not just use the array index. Updated code:
/*ProductList*/
getProductForms: function(product, index) {
return (
<div key={product.unique_id}>
<ProductForm
product={product}
/>
</div>
)
},
Is there not a simple way to pass a child's props to its parent using events, in React.js?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
I know you can use controlled components to pass an input's value but it'd be nice to pass the whole kit n' kaboodle. Sometimes the child component contains a set of information you'd rather not have to look up.
Perhaps there's a way to bind the component to the event?
UPDATE – 9/1/2015
After using React for over a year, and spurred on by Sebastien Lorber's answer, I've concluded passing child components as arguments to functions in parents is not in fact the React way, nor was it ever a good idea. I've switched the answer.
Edit: see the end examples for ES6 updated examples.
This answer simply handle the case of direct parent-child relationship. When parent and child have potentially a lot of intermediaries, check this answer.
Other solutions are missing the point
While they still work fine, other answers are missing something very important.
Is there not a simple way to pass a child's props to its parent using events, in React.js?
The parent already has that child prop!: if the child has a prop, then it is because its parent provided that prop to the child! Why do you want the child to pass back the prop to the parent, while the parent obviously already has that prop?
Better implementation
Child: it really does not have to be more complicated than that.
var Child = React.createClass({
render: function () {
return <button onClick={this.props.onClick}>{this.props.text}</button>;
},
});
Parent with single child: using the value it passes to the child
var Parent = React.createClass({
getInitialState: function() {
return {childText: "Click me! (parent prop)"};
},
render: function () {
return (
<Child onClick={this.handleChildClick} text={this.state.childText}/>
);
},
handleChildClick: function(event) {
// You can access the prop you pass to the children
// because you already have it!
// Here you have it in state but it could also be
// in props, coming from another parent.
alert("The Child button text is: " + this.state.childText);
// You can also access the target of the click here
// if you want to do some magic stuff
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
Parent with list of children: you still have everything you need on the parent and don't need to make the child more complicated.
var Parent = React.createClass({
getInitialState: function() {
return {childrenData: [
{childText: "Click me 1!", childNumber: 1},
{childText: "Click me 2!", childNumber: 2}
]};
},
render: function () {
var children = this.state.childrenData.map(function(childData,childIndex) {
return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
}.bind(this));
return <div>{children}</div>;
},
handleChildClick: function(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
It is also possible to use this.handleChildClick.bind(null,childIndex) and then use this.state.childrenData[childIndex]
Note we are binding with a null context because otherwise React issues a warning related to its autobinding system. Using null means you don't want to change the function context. See also.
About encapsulation and coupling in other answers
This is for me a bad idea in term of coupling and encapsulation:
var Parent = React.createClass({
handleClick: function(childComponent) {
// using childComponent.props
// using childComponent.refs.button
// or anything else using childComponent
},
render: function() {
<Child onClick={this.handleClick} />
}
});
Using props:
As I explained above, you already have the props in the parent so it's useless to pass the whole child component to access props.
Using refs:
You already have the click target in the event, and in most case this is enough.
Additionnally, you could have used a ref directly on the child:
<Child ref="theChild" .../>
And access the DOM node in the parent with
React.findDOMNode(this.refs.theChild)
For more advanced cases where you want to access multiple refs of the child in the parent, the child could pass all the dom nodes directly in the callback.
The component has an interface (props) and the parent should not assume anything about the inner working of the child, including its inner DOM structure or which DOM nodes it declares refs for. A parent using a ref of a child means that you tightly couple the 2 components.
To illustrate the issue, I'll take this quote about the Shadow DOM, that is used inside browsers to render things like sliders, scrollbars, video players...:
They created a boundary between what you, the Web developer can reach
and what’s considered implementation details, thus inaccessible to
you. The browser however, can traipse across this boundary at will.
With this boundary in place, they were able to build all HTML elements
using the same good-old Web technologies, out of the divs and spans
just like you would.
The problem is that if you let the child implementation details leak into the parent, you make it very hard to refactor the child without affecting the parent. This means as a library author (or as a browser editor with Shadow DOM) this is very dangerous because you let the client access too much, making it very hard to upgrade code without breaking retrocompatibility.
If Chrome had implemented its scrollbar letting the client access the inner dom nodes of that scrollbar, this means that the client may have the possibility to simply break that scrollbar, and that apps would break more easily when Chrome perform its auto-update after refactoring the scrollbar... Instead, they only give access to some safe things like customizing some parts of the scrollbar with CSS.
About using anything else
Passing the whole component in the callback is dangerous and may lead novice developers to do very weird things like calling childComponent.setState(...) or childComponent.forceUpdate(), or assigning it new variables, inside the parent, making the whole app much harder to reason about.
Edit: ES6 examples
As many people now use ES6, here are the same examples for ES6 syntax
The child can be very simple:
const Child = ({
onClick,
text
}) => (
<button onClick={onClick}>
{text}
</button>
)
The parent can be either a class (and it can eventually manage the state itself, but I'm passing it as props here:
class Parent1 extends React.Component {
handleChildClick(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
render() {
return (
<div>
{this.props.childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => this.handleChildClick(child,e)}
/>
))}
</div>
);
}
}
But it can also be simplified if it does not need to manage state:
const Parent2 = ({childrenData}) => (
<div>
{childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => {
alert("The Child button data is: " + child.childText + " - " + child.childNumber);
alert("The Child HTML is: " + e.target.outerHTML);
}}
/>
))}
</div>
)
JsFiddle
PERF WARNING (apply to ES5/ES6): if you are using PureComponent or shouldComponentUpdate, the above implementations will not be optimized by default because using onClick={e => doSomething()}, or binding directly during the render phase, because it will create a new function everytime the parent renders. If this is a perf bottleneck in your app, you can pass the data to the children, and reinject it inside "stable" callback (set on the parent class, and binded to this in class constructor) so that PureComponent optimization can kick in, or you can implement your own shouldComponentUpdate and ignore the callback in the props comparison check.
You can also use Recompose library, which provide higher order components to achieve fine-tuned optimisations:
// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}
// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)
// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)
In this case you could optimize the Child component by using:
const OptimizedChild = onlyUpdateForKeys(['text'])(Child)
Update (9/1/15): The OP has made this question a bit of a moving target. It’s been updated again. So, I feel responsible to update my reply.
First, an answer to your provided example:
Yes, this is possible.
You can solve this by updating Child’s onClick to be this.props.onClick.bind(null, this):
var Child = React.createClass({
render: function () {
return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>;
}
});
The event handler in your Parent can then access the component and event like so:
onClick: function (component, event) {
// console.log(component, event);
},
JSBin snapshot
But the question itself is misleading
Parent already knows Child’s props.
This isn’t clear in the provided example because no props are actually being provided. This sample code might better support the question being asked:
var Child = React.createClass({
render: function () {
return <a onClick={this.props.onClick}> {this.props.text} </a>;
}
});
var Parent = React.createClass({
getInitialState: function () {
return { text: "Click here" };
},
onClick: function (event) {
// event.component.props ?why is this not available?
},
render: function() {
return <Child onClick={this.onClick} text={this.state.text} />;
}
});
It becomes much clearer in this example that you already know what the props of Child are.
JSBin snapshot
If it’s truly about using a Child’s props…
If it’s truly about using a Child’s props, you can avoid any hookup with Child altogether.
JSX has a spread attributes API I often use on components like Child. It takes all the props and applies them to a component. Child would look like this:
var Child = React.createClass({
render: function () {
return <a {...this.props}> {this.props.text} </a>;
}
});
Allowing you to use the values directly in the Parent:
var Parent = React.createClass({
getInitialState: function () {
return { text: "Click here" };
},
onClick: function (text) {
alert(text);
},
render: function() {
return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />;
}
});
JSBin snapshot
And there's no additional configuration required as you hookup additional Child components
var Parent = React.createClass({
getInitialState: function () {
return {
text: "Click here",
text2: "No, Click here",
};
},
onClick: function (text) {
alert(text);
},
render: function() {
return <div>
<Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />
<Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} />
</div>;
}
});
JSBin snapshot
But I suspect that’s not your actual use case. So let’s dig further…
A robust practical example
The generic nature of the provided example is a hard to talk about. I’ve created a component that demonstrations a practical use for the question above, implemented in a very Reacty way:
DTServiceCalculator working example
DTServiceCalculator repo
This component is a simple service calculator. You provide it with a list of services (with names and prices) and it will calculate a total the selected prices.
Children are blissfully ignorant
ServiceItem is the child-component in this example. It doesn’t have many opinions about the outside world. It requires a few props, one of which is a function to be called when clicked.
<div onClick={this.props.handleClick.bind(this.props.index)} />
It does nothing but to call the provided handleClick callback with the provided index[source].
Parents are Children
DTServicesCalculator is the parent-component is this example. It’s also a child. Let’s look.
DTServiceCalculator creates a list of child-component (ServiceItems) and provides them with props [source]. It’s the parent-component of ServiceItem but it`s the child-component of the component passing it the list. It doesn't own the data. So it again delegates handling of the component to its parent-component source
<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem captures the index, passed from the child, and provides it to its parent [source]
handleServiceClick (index) {
this.props.onSelect(index);
}
Owners know everything
The concept of “Ownership” is an important one in React. I recommend reading more about it here.
In the example I’ve shown, I keep delegating handling of an event up the component tree until we get to the component that owns the state.
When we finally get there, we handle the state selection/deselection like so [source]:
handleSelect (index) {
let services = […this.state.services];
services[index].chosen = (services[index].chosen) ? false : true;
this.setState({ services: services });
}
Conclusion
Try keeping your outer-most components as opaque as possible. Strive to make sure that they have very few preferences about how a parent-component might choose to implement them.
Keep aware of who owns the data you are manipulating. In most cases, you will need to delegate event handling up the tree to the component that owns that state.
Aside: The Flux pattern is a good way to reduce this type of necessary hookup in apps.
It appears there's a simple answer. Consider this:
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick.bind(null, this)}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(component, event) {
component.props // #=> {Object...}
},
render: function() {
<Child onClick={this.onClick} />
}
});
The key is calling bind(null, this) on the this.props.onClick event, passed from the parent. Now, the onClick function accepts arguments component, AND event. I think that's the best of all worlds.
UPDATE: 9/1/2015
This was a bad idea: letting child implementation details leak in to the parent was never a good path. See Sebastien Lorber's answer.
The question is how to pass argument from child to parent component. This example is easy to use and tested:
//Child component
class Child extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
)
}
}
//Parent component
class Parent extends React.Component {
constructor(props) {
super(props);
var handleToUpdate = this.handleToUpdate.bind(this);
}
handleToUpdate(someArg){
alert('We pass argument from Child to Parent: \n' + someArg);
}
render() {
var handleToUpdate = this.handleToUpdate;
return (<div>
<Child handleToUpdate = {handleToUpdate.bind(this)} />
</div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<Parent />,
document.querySelector("#demo")
);
}
Look at JSFIDDLE
Basically you use props to send information to and from Child and Parent.
Adding to all the wonderful answers, let me give a simple example that explains passing values from child to parent component in React
App.js
class App extends React.Component {
constructor(){
super();
this.handleFilterUpdate = this.handleFilterUpdate.bind(this);
this.state={name:'igi'}
}
handleFilterUpdate(filterValue) {
this.setState({
name: filterValue
});
}
render() {
return (
<div>
<Header change={this.handleFilterUpdate} name={this.state.name} />
<p>{this.state.name}</p>
</div>
);
}
}
Header.js
class Header extends React.Component {
constructor(){
super();
this.state={
names: 'jessy'
}
}
Change(event) {
// this.props.change(this.state.names);
this.props.change('jessy');
}
render() {
return (
<button onClick={this.Change.bind(this)}>click</button>
);
}
}
Main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App />, document.getElementById('app'));
Thats it , now you can pass values from your client to the server.
Take a look at the Change function in the Header.js
Change(event) {
// this.props.change(this.state.names);
this.props.change('jessy');
}
This is how you push values into the props from client to the server
Here is a simple 3 step ES6 implementation using function binding in the parent constructor. This is the first way the official react tutorial recommends (there is also public class fields syntax not covered here). You can find all of this information here https://reactjs.org/docs/handling-events.html
Binding Parent Functions so Children Can Call Them (And pass data up to the parent! :D )
Make sure in the parent constructor you bind the function you created in the parent
Pass the bound function down to the child as a prop (No lambda because we are passing a ref to function)
Call the bound function from a child event (Lambda! We're calling the function when the event is fired.
If we don't do this the function will automatically run on load and not be triggered on the event.)
Parent Function
handleFilterApply(filterVals){}
Parent Constructor
this.handleFilterApply = this.handleFilterApply.bind(this);
Prop Passed to Child
onApplyClick = {this.handleFilterApply}
Child Event Call
onClick = {() => {props.onApplyClick(filterVals)}
This is an example without using the onClick event. I simply pass a callback function to the child by props. With that callback the child call also send data back. I was inspired by the examples in the docs.
Small example (this is in a tsx files, so props and states must be declared fully, I deleted some logic out of the components, so it is less code).
*Update: Important is to bind this to the callback, otherwise the callback has the scope of the child and not the parent. Only problem: it is the "old" parent...
SymptomChoser is the parent:
interface SymptomChooserState {
// true when a symptom was pressed can now add more detail
isInDetailMode: boolean
// since when user has this symptoms
sinceDate: Date,
}
class SymptomChooser extends Component<{}, SymptomChooserState> {
state = {
isInDetailMode: false,
sinceDate: new Date()
}
helloParent(symptom: Symptom) {
console.log("This is parent of: ", symptom.props.name);
// TODO enable detail mode
}
render() {
return (
<View>
<Symptom name='Fieber' callback={this.helloParent.bind(this)} />
</View>
);
}
}
Symptom is the child (in the props of the child I declared the callback function, in the function selectedSymptom the callback is called):
interface SymptomProps {
// name of the symptom
name: string,
// callback to notify SymptomChooser about selected Symptom.
callback: (symptom: Symptom) => void
}
class Symptom extends Component<SymptomProps, SymptomState>{
state = {
isSelected: false,
severity: 0
}
selectedSymptom() {
this.setState({ isSelected: true });
this.props.callback(this);
}
render() {
return (
// symptom is not selected
<Button
style={[AppStyle.button]}
onPress={this.selectedSymptom.bind(this)}>
<Text style={[AppStyle.textButton]}>{this.props.name}</Text>
</Button>
);
}
}