I am building my first React app and am doing an app that people can use to split their bills with others. The app is deployed on heroku through this link http://split-calc.herokuapp.com.
The problem I am having is the following:
Lets say you start by typing in 100 for Meal total, 20 for Shared Items, and 10 for tax and tip, resulting in a grand total of 140.
Next, you click the 'Add Person' button, which renders a Person component. Here you will see an input for 'Person subtotal'. Shared will automatically start at 20 because you are so far only splitting the bill with yourself. As you add a value to 'Person Subtotal', the tip, tax and total with dynamically update. Now the problem lies when you click 'Add Person' once again. Person #2 now has a Shard value of 10, which is correct because now the 'Shared Items', which was $20, is now being split by two people (20/2 = 10). The problem is, Person #1 still has a Shared value of $20. Now if you click 'Add Person' once again, the third person will have the correct shared value, but now person #1 and #2 have outdated values. How can I update these dynamically?
Below is all of my code so far.
function Header() {
return (
<header>Split Bill Calculator</header>
)
}
function AddPerson(props) {
return (
<div className='button'>
<button className='addPerson' onClick={props.onClicked}>Add Person</button>
</div>
);
}
function PersonList(props) {
return (
<div>
{props.persons.map((person, index) => (
<span key={index}>{person}</span>
))}
</div>
);
};
class Details extends React.Component {
constructor(props) {
super(props);
this.state = {
meal_total: 0,
shared_items: 0,
tax: 0,
tip: 0,
persons: [],
counter: 1,
};
this.handleClick = this.handleClick.bind(this)
this.handleMealChange = this.handleMealChange.bind(this)
this.handleSharedItemsChange = this.handleSharedItemsChange.bind(this)
this.handleTaxChange = this.handleTaxChange.bind(this)
this.handleTipChange = this.handleTipChange.bind(this)
}
handleMealChange = event => {
this.setState({
meal_total: event.target.value,
});
};
handleSharedItemsChange = event => {
this.setState({
shared_items: event.target.value,
});
};
handleTaxChange = event => {
this.setState({
tax: event.target.value,
});
};
handleTipChange = event => {
this.setState({
tip: event.target.value,
});
};
handleClick = () => {
let counter = this.state.counter + 1
let addPerson = this.state.persons.concat(this.renderPerson())
this.setState({
persons: addPerson,
counter: counter,
});
}
renderPerson = () => {
return (
<Person
person_tax = {this.state.tax}
person_tip = {this.state.tip}
shared_items = {this.state.shared_items}
counter = {this.state.counter}
/>
)
}
renderAddPerson = () => {
return (
<AddPerson
onClicked= {() => this.handleClick()}
/>
);
}
render() {
let grand_total = parseFloat(this.state.meal_total) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tax)/100)) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tip)/100));
return (
<div className='details'>
<div className='order-total'>
<form>
<label htmlFor='meal'>Meal subtotal: ($)</label><br></br>
<input name='meal' placeholder={this.state.meal_total} onChange={this.handleMealChange}></input><br></br>
<label htmlFor='meal'>Shared items: ($)</label><br></br>
<input name='meal' placeholder={this.state.shared_items} onChange={this.handleSharedItemsChange}></input><br></br>
<label htmlFor='tax'>Tax: (%)</label><br></br>
<input name='tax' placeholder={this.state.tax} onChange={this.handleTaxChange}></input><br></br>
<label htmlFor='tip'>Tip: (%)</label><br></br>
<input name='tip' placeholder={this.state.tip} onChange={this.handleTipChange}></input><br></br>
<label htmlFor='total'>Grand Total: ($)</label><br></br>
<input name='total' value={grand_total.toFixed(2)} readOnly></input><br></br>
</form>
</div>
<PersonList persons={this.state.persons} />
{this.renderAddPerson()}
</div>
);
}
}
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {
person_tax: props.person_tax,
person_tip: props.person_tip,
person_meal_subtotal: 0,
shared_items: props.shared_items,
}
}
handlePersonSubtotal = event => {
this.setState({
person_meal_subtotal: event.target.value
});
};
render() {
let person_total = parseFloat(this.state.person_meal_subtotal) + parseFloat(this.props.shared_items) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tax)/100)) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tip)/100));
let shared_items = this.state.shared_items / this.props.counter;
return (
<div className='person'>
<div className='total-details'>
<h3>Person {this.props.number} </h3>
<form>
<label htmlFor='person-meal'>Personal Subtotal: $ </label>
<input name='person-meal' value={this.state.person_meal_subtotal} onChange={this.handlePersonSubtotal}></input>
</form>
</div>
<div className='breakdown'>
<h3>Should Pay</h3>
<div className='person-details'>
<p>Shared: ${(parseFloat(shared_items)).toFixed(2)}</p>
<p>Tax: ${((parseFloat(this.state.person_tax)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p>
<p>Tip: ${((parseFloat(this.state.person_tip)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p>
<p>Total: ${person_total.toFixed(2)}</p>
</div>
</div>
</div>
)
}
}
class Calculator extends React.Component {
render() {
return (
<div>
<Header />
<Details/>
</div>
)
}
}
ReactDOM.render(<Calculator />, document.getElementById('root'));
You might want to do it later
handleClick = () => {
let counter = this.state.counter + 1
let addPerson = this.state.persons.concat(this.renderPerson())
this.setState({
persons: addPerson,
counter: counter,
});
}
instead of this
try this
handleClick = () => {
let counter = this.state.counter + 1
this.setState({
persons: addPerson,
counter: counter,
}, () => {
let addPerson = this.state.persons.concat(this.renderPerson())
this.setState({
persons: addPerson
});
});
}
Related
i am trying to do a simple toDo app with react. I couldnt do how to delete an element in list. Here my code; first state:
class AppForm extends Component {
constructor(props) {
super(props);
this.state = { items: [] , text:''};
this.onChangeHandler=this.onChangeHandler.bind(this)
this.submitHandler=this.submitHandler.bind(this)
}
//setting input value to the text in state
onChangeHandler = (e) => {
this.setState({
text: e.target.value
});
};
//pushing text item of the state to the items
submitHandler = (e) => {
e.preventDefault();
const arrayItem = {
text: this.state.text,
};
this.setState(state => ({
items: state.items.concat(arrayItem),
text: ''
}));
}
here the problem area. I also tried splice but couldnt.
deleteItem=(index)=>{
let todos= this.state.items.filter(todo => index !== todo.key)
this.setState({
items : todos
})
}
then rendering..
render() {
return (
<div>
<h1>toDo App</h1>
<form onSubmit={this.submitHandler}>
<label>Type the task you want to do!</label>
<input type="text" onChange={this.onChangeHandler} value={this.state.text}/>
</form>
<ul>
{this.state.items.map((item,index) =>{
return (
<li key={index}> {item.text}
<p onClick={this.deleteItem.bind(this,index)}> X </p>
</li>
)
})}
</ul>
</div>
);
}
}
export default AppForm;
Splice is the answer.
First, I create a copy of your state array. Then splice it using the index clicked. Then set setState with the spliced array.
deleteItem=(index)=>{
let todos= [...this.state.items]
todos.splice(index, 1)
this.setState({
items : todos
})
}
deleteItem = (index) => {
this.setState(({items}) => {
return {items: [...items.filter(todo => index !== todo.key)]};
})
}
First of all you're not setting the key anywhere when you are inserting in array. It is not at all recommended to use index as key in array. It should be unique.
const arrayItem = {
text: this.state.text,
id: uuid()
};
So I've added the uuid and compared with the id of the element.
codesandbox
uuid
// UNIQUE KEY GENERATOR
function uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
export default uuidv4;
React component
import React, { Component } from "react";
import uuid from "./uuid";
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = { items: [], text: "" };
this.onChangeHandler = this.onChangeHandler.bind(this);
this.submitHandler = this.submitHandler.bind(this);
}
//setting input value to the text in state
onChangeHandler = (e) => {
this.setState({
text: e.target.value
});
};
//pushing text item of the state to the items
submitHandler = (e) => {
e.preventDefault();
const arrayItem = {
text: this.state.text,
id: uuid()
};
this.setState((state) => ({
items: state.items.concat(arrayItem),
text: ""
}));
};
deleteItem = (key) => {
let todos = this.state.items.filter((todo) => key !== todo.id);
this.setState({
items: todos
});
};
render() {
return (
<div>
<h1>toDo App</h1>
<form onSubmit={this.submitHandler}>
<label>Type the task you want to do!</label>
<input
type="text"
onChange={this.onChangeHandler}
value={this.state.text}
/>
</form>
<ul>
{this.state.items.map((item) => {
return (
<li key={item.id}>
{item.text}
<p onClick={() => this.deleteItem(item.id)}> X </p>
</li>
);
})}
</ul>
</div>
);
}
}
export default App;
I just created my first React app, https://split-calc.herokuapp.com/
If I fill out the top form first and then click 'Add Person', everything works normal. However, if I click 'Add Person' before filling out the top form, once I fill out the top form, none of the numbers for Person are updated. Why is this happening even though I set each value to be linked to state?
function Header() {
return (
<header>Split Bill Calculator</header>
)
}
function AddPerson(props) {
return (
<div className='button'>
<button className='addPerson' onClick={props.onClicked}>Add Person</button>
</div>
);
}
function PersonList(props) {
return (
<div>
{props.persons.map((person, index) => (
<span key={index}>{person}</span>
))}
</div>
);
};
class Details extends React.Component {
constructor(props) {
super(props);
this.state = {
meal_total: 0,
shared_items: 0,
tax: 0,
tip: 0,
persons: [],
counter: 1,
};
this.handleClick = this.handleClick.bind(this)
this.handleMealChange = this.handleMealChange.bind(this)
this.handleSharedItemsChange = this.handleSharedItemsChange.bind(this)
this.handleTaxChange = this.handleTaxChange.bind(this)
this.handleTipChange = this.handleTipChange.bind(this)
}
handleMealChange = event => {
this.setState({
meal_total: event.target.value,
});
};
handleSharedItemsChange = event => {
this.setState({
shared_items: event.target.value,
});
};
handleTaxChange = event => {
this.setState({
tax: event.target.value,
});
};
handleTipChange = event => {
this.setState({
tip: event.target.value,
});
};
handleClick = () => {
let counter = this.state.counter + 1
let addPerson = this.state.persons.concat(this.renderPerson())
this.setState({
persons: addPerson,
counter: counter,
});
}
renderPerson = () => {
return (
<Person
person_tax = {this.state.tax}
person_tip = {this.state.tip}
shared_items = {this.state.shared_items}
counter = {this.state.counter}
/>
)
}
renderAddPerson = () => {
return (
<AddPerson
onClicked= {() => this.handleClick()}
/>
);
}
render() {
let grand_total = parseFloat(this.state.meal_total) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tax)/100)) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tip)/100));
return (
<div className='details'>
<div className='order-total'>
<form>
<label htmlFor='meal'>Meal subtotal: ($)</label><br></br>
<input name='meal' placeholder={this.state.meal_total} onChange={this.handleMealChange}></input><br></br>
<label htmlFor='meal'>Shared items: ($)</label><br></br>
<input name='meal' placeholder={this.state.shared_items} onChange={this.handleSharedItemsChange}></input><br></br>
<label htmlFor='tax'>Tax: (%)</label><br></br>
<input name='tax' placeholder={this.state.tax} onChange={this.handleTaxChange}></input><br></br>
<label htmlFor='tip'>Tip: (%)</label><br></br>
<input name='tip' placeholder={this.state.tip} onChange={this.handleTipChange}></input><br></br>
<label htmlFor='total'>Grand Total: ($)</label><br></br>
<input name='total' value={grand_total.toFixed(2)} readOnly></input><br></br>
</form>
</div>
<PersonList persons={this.state.persons} />
{this.renderAddPerson()}
</div>
);
}
}
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {
person_tax: props.person_tax,
person_tip: props.person_tip,
person_meal_subtotal: 0,
shared_items: props.shared_items,
}
}
handlePersonSubtotal = event => {
this.setState({
person_meal_subtotal: event.target.value
});
};
render() {
let person_total = parseFloat(this.state.person_meal_subtotal) + parseFloat(this.props.shared_items) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tax)/100)) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tip)/100));
let shared_items = this.state.shared_items / this.props.counter;
return (
<div className='person'>
<div className='total-details'>
<h3>Person {this.props.counter} </h3>
<form>
<label htmlFor='person-meal'>Personal Subtotal: $ </label>
<input name='person-meal' value={this.state.person_meal_subtotal} onChange={this.handlePersonSubtotal}></input>
</form>
</div>
<div className='breakdown'>
<h3>Should Pay</h3>
<div className='person-details'>
<p>Shared: ${(parseFloat(shared_items)).toFixed(2)}</p><br></br>
<p>Tax: ${((parseFloat(this.state.person_tax)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p><br></br>
<p>Tip: ${((parseFloat(this.state.person_tip)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p><br></br>
<p>Total: ${person_total.toFixed(2)}</p>
</div>
</div>
</div>
)
}
}
class Calculator extends React.Component {
render() {
return (
<div>
<Header />
<Details/>
</div>
)
}
}
ReactDOM.render(<Calculator />, document.getElementById('root'));
First suggestion would be if the form is not filled do not allow the user to add persons.
Based on the analysis of the above code, you are not linking state with number of persons array of object and not updating the values. only global data on state is getting updated on each change.
this.state = {
meal_total: 0, /*updated*/
shared_items: 0, /*updated*/
tax: 0, /*updated*/
tip: 0, /*updated*/
persons: [], /*not updated on each action update, its only getting re-render or getting the state during new person add action*/
counter: 1, /*updated*/
};
You need to update the state.persons: [] each actions to the unique persons array
handleTaxChange = event => {
this.setState({
tax: event.target.value,
persons: <-- update the number of persons selected array with tax -->
});
};
Code that calls the render person list which seems having old values each time rendering->
<PersonList persons={this.state.persons} />
You need to access and update the tax for individual person.
Happy Coding!
I have made a toaster component of my own which on multiple clicks render multiple toasters. The problem I am facing is that all the toasters are terminated when the handle close component is clicked or when the settimeout function is called. I am passing messages through another component as props.
This is my toaster component
export default class MyToaster extends React.Component {
constructor(props) {
super(props);
this.state = {
message: props.message,
show: false,
no: 0
};
}
handleclose = () => {
this.setState({
show: false,
no: this.state.no - 1
})
}
handleOpen = () => {
console.log('HANDLE OPEN')
this.setState({
show: true,
no: this.state.no + 1
}, () => {
setTimeout(() => {
this.setState({
show: false,
no: this.state.no - 1
})
}, 3000)
})
}
createtoaster = () => {
if (this.state.show) {
let toastmessage = [];
for (let i = 0; i < this.state.no; i++) {
let tmessage = <div className="snackbar">
<div className="card-header">
<h3 className="card-title">Toast</h3>
</div>
<div className="card-body">
{this.state.message}
</div>
<div className="card-footer"></div>
<button className="btn" onClick={this.handleclose}>x</button>
</div>
toastmessage.push(tmessage);
}
return toastmessage;
} else {
return null;
}
};
render() {
return (
<div className="col-md-2 offset-md-9">
<button className="btn btn-primary" onClick={this.handleOpen}></button>
{this.createtoaster()}
</div>
)
}
}
I have tried managing the state in the parent component but it doesnt seem to work. I do know that the problem is in managing state of my toaster component but dont know the exact problem and the solution.
Any solutions for this also feel free to point out any of my mistakes.
TIA
Handle close is run on the click of any button rather on the instance of one of them by the looks of it.
if (this.state.show) { // this determines whether to render you toasts...
// and close turns all of them off.
You need to change each toast to have it's own show property and for close to toggle that one and remove it from the array of toasts to generate.
Note:
Your props and state should be separate, don't copy props into state as this will introduce bugs and changes will not be reflected.
constructor(props) {
super(props);
// avoid copying props into state
// https://reactjs.org/docs/react-component.html#constructor
this.state = {
message: props.message,
show: false,
no: 0
};
}
There is a different way to this approach.
export default class MyToaster extends React.Component {
constructor(props) {
super(props);
this.state = {
message: props.message,
show: true,
no: 0
};
}
componentDidMount() {
setTimeout(() => {
this.setState({show: false})
}, 4000)
}
handleclose = () => {
this.setState({
show: false,
no: this.state.no - 1
})
}
handleOpen = () => {
this.setState({
no: this.state.no + 1
}, () => {
setTimeout(() => {
this.setState({
show: false,
no: this.state.no - 1
})
}, 3000)
})
}
render() {
return (
<div className="col-md-2 offset-md-9">
{this.state.show
? (
<div className="container snackbar" style={this.props.style}>
<div className="card-header">
<h3 className="card-title">Toast</h3>
</div>
<div className="card-body">
{this.props.message}
</div>
<div className="card-footer"></div>
</div>
)
: null
}
</div>
)
}
}
And from your parent component you can include
this.state = {
toasterCollection: []
}
//make a function
handleToasterClick = () => {
const toaster = <Toaster message={this.message} style={this.style}/>
this.setState({
// toasterCollection: [...this.state.toasterCollection, toaster]
toasterCollection: [...this.state.toasterCollection, toaster]
});
}
//In your Render give a button
<button className="btn btn-primary" onClick={this.handleToasterClick}>
Toast
</button>
//Also render this
{this.state.toasterCollection}
This should get your code to work.
I am trying to pass in props to a component which works while using componentWillReceiveProps, but once the counter is done it calls clearInterval(this.intervalId);However once I change the input again the counter does not get initiated again. How can i pass the updated props back to the component?
Component code;
class Stopwatch extends Component {
constructor(props) {
super(props);
this.state = {
currentCount: this.props.counter,
hours: 0,
minutes: 0,
seconds: 0
}
}
componentWillMount() {
this.timer(this.props.counter);
}
timer() {
this.setState({
currentCount: this.state.currentCount - 1
})
const seconds = Math.floor(this.state.currentCount % 60);
const minutes = Math.floor((this.state.currentCount/60) % 60);
const hours = Math.floor((this.state.currentCount/3600) % 3600);
this.setState({hours, minutes, seconds});
if (this.state.currentCount < 1) {
clearInterval(this.intervalId);
}
}
componentDidMount() {
this.intervalId = setInterval(this.timer.bind(this), 1000);
}
leading0(num) {
return num < 10 ? '0' + num : num;
}
componentWillReceiveProps(nextProps){
if(nextProps.counter !== this.props.counter){
this.setState ({currentCount: nextProps.counter})
}
}
render() {
return (
<div>
<div>Hours {this.leading0(this.state.hours)}</div>
<div>Minutes {this.leading0(this.state.minutes)}</div>
<div>Seconds {this.leading0(this.state.seconds)}</div>
</div>
)
Main Code;
class App extends Component {
constructor(props) {
super(props);
this.state = {
deadline: 'December 25, 2018',
newDeadline: '',
counter: 75,
newCounter: ''
};
}
changeDeadline() {
this.setState({deadline: this.state.newDeadline});
}
changeNumber(e) {
this.setState({counter: this.state.newCounter});
}
render() {
return (
<div className='App'>
<div className='App-title'>Countdown to {this.state.deadline}</div>
<Clock
deadline={this.state.deadline}
/>
<Form inline>
<FormControl
className="Deadline-input"
placeholder='New Date'
onChange={event => this.setState({newDeadline: event.target.value})}
/>
<Button onClick={() => this.changeDeadline()}>Submit</Button>
</Form>
<div>Stopwatch From { this.state.counter } Seconds</div>
<Stopwatch
counter={this.state.counter}
/>
<Form inline>
<FormControl
className="Deadline-input"
placeholder='New Number'
onChange={event => this.setState({newCounter: event.target.value})}
/>
<Button onClick={() => this.changeNumber()}>Submit</Button>
</Form>
</div>
)
}
Thanks in Advance
componentDidMount function calls once, if you want to reset counter on props change, you should do it in componentWillReceiveProps function
class Stopwatch extends Component {
// ...
resetInterval() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
this.intervalId = setInterval(this.timer.bind(this), 1000);
}
componentWillReceiveProps(nextProps){
if(nextProps.counter !== this.props.counter){
this.setState ({currentCount: nextProps.counter})
// reset interval
this.resetInterval()
}
}
//...
}
I have search function where on entering text it returns the object from an array(json data) and based on the condition (whether it as an object or not) I need to show two different components ie. the list with matched fields and "No matched results found" component.
class Search extends React.Component {
constructor(props) {
super(props);
this.state = {
searchTextData: '',
isSearchText: false,
isSearchOpen: false,
placeholderText:'Search Content',
filteredMockData: [],
dataArray: []
};
}
handleSearchChange = (event, newVal) => {
this.setState({ searchTextData: newVal })
if (newVal == '') {
this.setState({ clearsearch: true });
this.setState({
filteredMockData: []
});
this.props.onDisplayCloseIcon(true);
} else {
this.props.onDisplayCloseIcon(false);
searchData.searchResults.forEach((item, index, array) => {
this.state.dataArray.push(item);
});
this.setState({ filteredMockData: this.state.dataArray });
}
}
clearInput = () => {
this.setState({ searchTextData: '' })
}
isSearchText = () => {
this.setState({ isSearchText: !this.state.isSearchText });
}
onSearchClick = () => {
this.setState({ isSearchOpen: !this.state.isSearchOpen });
this.setState({ searchTextData: '' });
this.props.onDisplayCloseIcon(true);
}
renderSearchData = () => {
const SearchDatasRender = this.state.dataArray.map((key) => {
const SearchDataRender = key.matchedFields.pagetitle;
return (<ResultComponent results={ SearchDataRender } /> );
})
return SearchDatasRender;
}
renderUndefined = () => {
return ( <div className = "search_no_results" >
<p> No Recent Searches found. </p>
<p> You can search by word or phrase, glossary term, chapter or section.</p>
</div>
);
}
render() {
return ( <span>
<SearchIcon searchClick = { this.onSearchClick } />
{this.state.isSearchOpen &&
<div className = 'SearchinputBar' >
<input
placeholder={this.state.placeholderText}
className= 'SearchInputContent'
value = { this.state.searchTextData}
onChange = { this.handleSearchChange }
/>
</div>
}
{this.state.searchTextData !== '' && this.state.isSearchOpen &&
<span className='clearText'>
<ClearIcon className='clearIcon' clearClick = { this.clearInput }/>
</span>
}
{this.state.searchTextData !== '' && this.state.isSearchOpen &&
<div className="SearchContainerWrapper">
<div className = "arrow-up"> </div>
<div className = 'search_result_Container' >
<div className = "search_results_title" > <span> Chapters </span><hr></hr> </div>
<div className="search_show_text" >
<ul className ="SearchScrollbar">
{this.state.filteredMockData.length ? this.renderSearchData() : this.renderUndefined() }
</ul>
</div>
</div>
</div>}
</span>
);
}
}
Search.propTypes = {
intl: intlShape.isRequired,
onSearchClick: PropTypes.func,
isSearchBarOpen: PropTypes.func,
clearInput: PropTypes.func,
isSearchText: PropTypes.func
};
export default injectIntl(Search);
Search is my parent component and based on the matched values I need to show a resultComponent like
class ResultComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render(){
console.log(this.props.renderSearchData(),'Helloooo')
return(<p>{this.props.renderSearchData()}</p>)
}
}
ResultComponent.propTypes = {
results: PropTypes.string.isRequired
};
I'm getting an error "renderSearchData is not an function".I'm new to react and Hope someone can help.
The only prop passed to ResultComponent component is results
So in ResultComponent Component Replace
this.props.renderSearchData()
With
this.props.results