Gatsby Stripe Checkout - multiple quantities - reactjs

I'm following this Gatsby guide - https://www.gatsbyjs.org/tutorial/ecommerce-tutorial/
I would like to modify this code to allow the user to change the number of items they can purchase.
Following this React guide - https://reactjs.org/docs/forms.html - I am adding an <input> field to allow a quantity to be chosen.
I then want to pass the value to here - items: [{ sku: "XXXXXXXX", quantity: 1 }]
The error I get is TypeError: _this.handleInputChange is undefined on the line this.handleInputChange = this.handleInputChange.bind(this);
Any pointers would be great, thanks.
import React from "react"
const Checkout = class extends React.Component {
constructor(props) {
super(props);
this.state = {
numberOfItems: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
componentDidMount() {
this.stripe = window.Stripe("XXXXXXX")
}
async redirectToCheckout(event) {
event.preventDefault()
const { error } = await this.stripe.redirectToCheckout({
items: [{ sku: "XXXXXXXX", quantity: 1 }],
successUrl: `http://localhost:8000/thank-you`,
cancelUrl: `http://localhost:8000/`,
})
if (error) {
console.warn("Error:", error)
}
}
render() {
return (
<div>
<label>
Number to buy
<input
name="numberOfItems"
type="number"
value={this.state.numberOfItems}
onChange={this.handleInputChange} />
</label>
<button
onClick={event => this.redirectToCheckout(event)}
>
Buy Now
</button>
</div>
)
}
}
export default Checkout
Update: I went with a different solution in the end:
import React from "react"
const Checkout = class extends React.Component {
state = { count: 1 }
handleIncrement = () => {
this.setState({ count: this.state.count + 1 })
}
handleDecrement = () => {
if(this.state.count > 1){
this.setState({ count: this.state.count - 1 })
}
}
componentDidMount() {
this.stripe = window.Stripe("")
}
async redirectToCheckout(event) {
event.preventDefault()
const { error } = await this.stripe.redirectToCheckout({
items: [{ sku: "", quantity: this.state.count }],
successUrl: `http://localhost:8000/thank-you`,
cancelUrl: `http://localhost:8000/`,
})
if (error) {
console.warn("Error:", error)
}
}
render() {
return (
<div>
<button onClick={this.handleIncrement}>+</button>
<div>
{this.state.count}
</div>
<button onClick={this.handleDecrement}>-</button>
<button
onClick={event => this.redirectToCheckout(event)}
>
Buy
</button>
</div>
)
}
}
export default Checkout

There is no such function handleInputChange in your class.
I believe you forgot to implement it in your class, for example:
import React from 'react';
const Checkout = class extends React.Component {
constructor(props) {
super(props);
this.state = {
numberOfItems: 2,
inputValue
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
this.setState({ inputValue: e.target.value });
}
render() {
return (
<div>
<label>
Number to buy
<input
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
</label>
</div>
);
}

Related

React: TodoList: Give an Input to an Array

I am currently working on a React Todo app. I'm still a React beginner, I've watched all kinds of tutorials but I can't find a solution to my problem.
I'm trying to process the text field (describtion) so that it creates a new array Element.
I pass the describtion into the function createTodo. There, a new object is created that contains the describtion and an id. This object is then pushed into the array TODOS.
My problem is that the describtion is undefined every time.
Please help and thank you:)
Translated with www.DeepL.com/Translator (free version)
import React from 'react';
import ReactDOM from 'react-dom';
class TodoTable extends React.Component {
constructor(props){
super(props);
this.state = {
enterTodo: '',
status: false
}
this.handleEnterTodo = this.handleEnterTodo.bind(this);
this.handleStatus = this.handleStatus.bind(this);
this.createTodo = this.createTodo.bind(this);
}
handleEnterTodo(event){
this.setState({
enterTodo: this.props.value
});
}
handleStatus(event){
this.setState({
status: this.props.true
});
}
createTodo(event){
const todo = {
id: 5,
describtion: this.props.enterTodo
}
TODOS.push(todo);
console.log(this.props.enterTodo);
}
render(){
const todos = this.props.todos;
//Gibt handleListener Funktionen an Child Komponente als Props weiter
return(
<>
<InputBar createTodo={this.createTodo} handleEnterTodo={this.handleEnterTodo} enterTodo={this.state.enterTodo}/>
<Todo handleStatus={this.handleStatus} status={this.state.status} todos={todos} />
</>
);
}
}
class InputBar extends React.Component {
render(){
return(
<form>
<input type='text' placeholder='Type in a Note'
value={this.props.enterTodo}
onChange= { this.props.handleEnterTodo }
/>
<button type='button' onClick={this.props.createTodo}>Enter</button>
<button>Clear Done</button>
</form>
);
}
}
class Todo extends React.Component {
render(){
const todoList = [];
this.props.todos.forEach((element, index) => {
let todo = <div><form>{this.props.todos[index].describtion}<input type='checkbox' checked={this.props.status} onChange={this.props.handleStatus} /></form></div>;
todoList.push(todo);
})
return(
todoList
);
}
}
//Mockdaten
let TODOS = [
{
id: 0,
describtion: 'Work more',
status: 'open'
},
{
id: 1,
describtion: 'Sleep more',
status: 'open'
},
{
id: 2,
describtion: 'Drink less',
status: 'done'
},
{
id: 3,
describtion: 'Learn more',
status: 'done'
},
];
//Render App
ReactDOM.render(
<TodoTable todos={TODOS} />,
document.getElementById('root')
);
Try this approach,
import "./styles.css";
import React from "react";
let TODOS = [
{
id: 0,
describtion: "Work more",
status: "open"
},
{
id: 1,
describtion: "Sleep more",
status: "open"
},
{
id: 2,
describtion: "Drink less",
status: "done"
},
{
id: 3,
describtion: "Learn more",
status: "done"
}
];
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<TodoTable todos={TODOS} />
</div>
);
}
class TodoTable extends React.Component {
constructor(props) {
super(props);
this.state = {
enterTodo: "",
todos: this.props.todos,
status: false
};
this.handleEnterTodo = this.handleEnterTodo.bind(this);
this.handleStatus = this.handleStatus.bind(this);
this.createTodo = this.createTodo.bind(this);
}
handleEnterTodo(event) {
this.setState({
enterTodo: event.target.value
});
}
handleStatus(event) {
this.setState({
status: this.props.true
});
}
createTodo(event) {
const todo = {
id: 5,
describtion: this.state.enterTodo
};
this.setState({
todos: [...this.state.todos, todo]
});
}
render() {
const todos = this.state.todos;
//Gibt handleListener Funktionen an Child Komponente als Props weiter
return (
<>
<InputBar
createTodo={this.createTodo}
handleEnterTodo={this.handleEnterTodo}
enterTodo={this.state.enterTodo}
/>
<Todo
handleStatus={this.handleStatus}
status={this.state.status}
todos={todos}
/>
</>
);
}
}
class InputBar extends React.Component {
render() {
return (
<form>
<input
type="text"
placeholder="Type in a Note"
value={this.props.enterTodo}
onChange={this.props.handleEnterTodo}
/>
<button type="button" onClick={this.props.createTodo}>
Enter
</button>
<button>Clear Done</button>
</form>
);
}
}
class Todo extends React.Component {
render() {
const todoList = [];
this.props.todos.forEach((element, index) => {
let todo = (
<div>
<form>
{this.props.todos[index].describtion}
<input
type="checkbox"
checked={this.props.status}
onChange={this.props.handleStatus}
/>
</form>
</div>
);
todoList.push(todo);
});
return todoList;
}
}
You shouldn't update the props value. instead, create a list in the local state itself. And use the local state value for render the template.
Also, You should access entered description value from the event object like below.
handleEnterTodo(event) {
this.setState({
enterTodo: event.target.value
});
}
codesandbox- https://codesandbox.io/s/compassionate-ride-k5gdus?file=/src/App.js

Axios post method in react isn't working: suggestions?

I'm trying to update a database with a user's text input, and it isn't working, even after trying a bunch of different approaches.
The text input is controlled by the following component:
import React from 'react'
class Dogue extends React.Component {
constructor(props){
super(props)
this.state = {
id: '',
nameInput:''
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(e) {
this.setState({
id: Date.now(),
nameInput: e.target.value
})
}
handleSubmit(e){
e.preventDefault()
this.props.inputFunction(this.state.nameInput, this.state.id)
}
render(){
console.log(this.props.id)
return (
<div className = 'dogue-container'>
<img className = 'img' src = {this.props.dogList}/>
<br/>
<form onSubmit = {this.handleSubmit} className = 'form'>
<input
onChange ={this.handleChange}
className ='input'
type = 'text'
placeholder = 'Enter dog name'
/>
<br/>
<button className = 'button'>Submit</button>
</form>
<h2 className = 'text'>Name: {this.props.name} </h2>
</div>
)
}
}
export default Dogue
and the state update and post is controlled by the App component:
import React, { Component } from "react";
import './styles.css'
import DogList from "./DogList";
import axios from "axios";
class App extends React.Component {
constructor() {
super();
this.state = {
loading: false,
dog: [],
dogName: [],
newName:''
};
this.updateStateWithInput = this.updateStateWithInput.bind(this)
}
setData = async () => {
const x = await fetch("https://dog.ceo/api/breed/hound/images");
const y = await x.json();
const z = await y.message;
let newArr = [];
for (let i = 0; i < z.length; i++) {
if (i <= 9) {
newArr.push(z[i]);
}
}
return newArr;
};
async componentDidMount() {
this.setState({
loading: true
});
let dogPromise = await this.setData();
let dogNamePromise = await axios.get('http://localhost:3000/dogs');
this.setState({
loading: false,
dog: dogPromise,
dogName: dogNamePromise.data
});
}
//Here is the function to update state and make axios post
async updateStateWithInput (nameInput,id) {
let newDog={id:id, dogName:nameInput}
this.setState({
dogName: this.state.dogName.push(newDog)
})
await axios.post('http://localhost:3000/dogs', this.state.dogName)
.then(res => {
console.log(res)
})
}
render() {
return this.state.loading ? (
<h1 className = 'text'> Dogues Loading.....</h1>
) : (
<div>
<h1 className = 'text'>Rate My Dogue</h1>
<DogList
dogs={this.state.dog}
name={this.state.dogName}
inputFunction = {this.updateStateWithInput}
/>
</div>
);
}
}
export default App
Basically, all I'm trying to do is update an array of objects, with a new object - example as follows:
//existing array:
[
{
id: 1,
dogName: 'bruce',
},
{
id: 2,
dogName: 'borker',
},
{
id: 3,
dogName: 'henry',
},
];
//new object to be pushed into array:
{id: id of some sort, dogName: the text input from the user}
Either you use await or use then, cannot use both:
const res = await axios.post('http://localhost:3000/dogs', this.state.dogName);
console.log(res)

How to make an axios POST request in React?

So, some context: Users submit a dog name via a text input, and this is controlled by the 'Dogue.jsx' component:
import React from 'react';
class Dogue extends React.Component {
constructor(props) {
super(props);
this.state = {
id: props.id,
nameInput: '',
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
nameInput: e.target.value,
});
}
handleSubmit(e) {
e.preventDefault();
this.props.inputFunction(this.state.nameInput);
}
render() {
console.log(this.props.id);
return (
<div className="dogue-container">
<img className="img" src={this.props.dogList} />
<br />
<form onSubmit={this.handleSubmit} className="form">
<input
onChange={this.handleChange}
className="input"
type="text"
placeholder="Enter dog name"
/>
<br />
<button className="button">Submit</button>
</form>
<h2 className="text">Name: {this.props.name} </h2>
</div>
);
}
}
export default Dogue;
The submitted information is then passed to 'App.jsx', where it is used to update state:
import React, {Component} from 'react';
import './styles.css';
import DogList from './DogList';
import axios from 'axios';
class App extends React.Component {
constructor() {
super();
this.state = {
loading: false,
dog: [],
dogName: [],
};
this.updateStateWithInput = this.updateStateWithInput.bind(this);
}
setData = async () => {
const x = await fetch('https://dog.ceo/api/breed/hound/images');
const y = await x.json();
const z = await y.message;
let newArr = [];
for (let i = 0; i < z.length; i++) {
if (i <= 9) {
newArr.push(z[i]);
}
}
return newArr;
};
async componentDidMount() {
this.setState({
loading: true,
});
let dogPromise = await this.setData();
let dogNamePromise = await axios.get('http://localhost:3000/dogs');
this.setState({
loading: false,
dog: dogPromise,
dogName: dogNamePromise.data,
});
}
updateStateWithInput(nameInput) {
//Here is where state is updated.
//change state, then use axios.post to submit data
}
render() {
return this.state.loading ? (
<h1 className="text"> Dogues Loading.....</h1>
) : (
<div>
<h1 className="text">Rate My Dogue</h1>
<DogList
dogs={this.state.dog}
name={this.state.dogName}
inputFunction={this.updateStateWithInput}
/>
</div>
);
}
}
export default App;
The updated state, I imagine, will be used in the axios post request to submit data to the database. So, I've got input data being sent from Dogue to App, I'm just not sure what to do now? The information currently in state looks as follows:
[
{
id: 1,
dogName: 'bruce',
},
{
id: 2,
dogName: 'borker',
},
{
id: 3,
dogName: 'henry',
},
];
I should also show my map function, in DogList.jsx:
import React from 'react';
import Dogue from './Dogue';
const DogList = (props) => {
return (
<div className="img-container">
{props.dogs.map((doggie, index) => {
return (
<Dogue
id={props.name[index] && props.name[index].id}
key={index}
dogList={doggie}
name={props.name[index] && props.name[index].dogName}
inputFunction={props.inputFunction}
/>
);
})}
</div>
);
};
export default DogList;
You can send a POST request with axios by calling:
axios.post(url, data, options);
It’s similar to the way you called the get method to make a GET request.
I’m leaving this axios cheat sheet here since it’s really useful until you get the hang of it:
https://kapeli.com/cheat_sheets/Axios.docset/Contents/Resources/Documents/index

Rerender another component when the state is changed

I want to rerender my another component when the state is changed. I've conditional components. One of them is related to input in my main component. It is rendered in the first place but I cant rerender it when I change the input value (also state value). The component is SearchGifList
import React from 'react';
import logo from './logo.svg';
import './App.css';
import TrendingGifList from './TrendingGifList';
import SearchGifList from './SearchGifList';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
search: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
this.setState({
search : true,
})
}
getTrendingGifs = () => {
this.setState({
search : false,
value: ''
})
}
getComponent = () => {
if(this.state.search) {
return <SearchGifList value={this.state.value} />
}
else {
return <TrendingGifList />
}
}
render() {
return (
<>
<div>
<a onClick={this.getTrendingGifs}>Logo</a>
<form onSubmit={this.handleSubmit}>
<input className="input-search" type="text" value={this.state.value} onChange={this.handleChange} />
<button type="submit" >Search</button>
</form>
</div>
<div>
{this.getComponent()}
</div>
</>
);
}
}
export default App;
SearchGifList Component code:
import React, { Component } from 'react';
import Masonry from 'react-masonry-css';
import {API_KEY, API_URL_search} from './constants'
class SearchGifList extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: [],
breakpointColumnsObj : {
default: 4,
1100: 3,
700: 2,
500: 1
},
offset: 0,
limit: 20,
api_key: API_KEY,
total_count: 0,
value: this.props.value
};
}
searchGifs = () => {
fetch( API_URL_search +
"?q=" + this.state.value +
"&api_key=" + this.state.api_key +
"&limit=" + this.state.limit +
"&offset=" + this.state.offset)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: (this.state.items).concat(result.data),
total_count: result.pagination.total_count,
offset : this.state.offset + 20
});
},
(error) => {
this.setState({
isLoaded: true,
error : 'Somethings went wrong to search gifs.'
});
}
)
}
componentDidMount() {
this.searchGifs();
}
loadMore = () => {
if(this.state.offset < this.state.total_count){
this.setState({
offset : this.state.offset + 20
});
}
this.searchGifs();
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<>
<Masonry
breakpointCols={this.state.breakpointColumnsObj}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column"
>
{items.map(item => (
<div className="gif-container" >
<img className="gif-preview" height={item.images.fixed_width.height} src={item.images.fixed_width.webp} alt="giphy baby" />
</div>
))}
</Masonry>
<button onClick={this.loadMore}>Load More</button>
</>
);
}
}
}
export default SearchGifList;
It should render content after changing state. Here is an similar example I have created for you now. https://codesandbox.io/embed/example-ys041
Please check it I think that will help you a lot.
If still you are not getting any idea then send me the your example via codesandbox I will check it for you.
Thanks
I solved the problem componentDidUpdate() method:
componentDidUpdate(prevProps) {
if (this.props.value !== prevProps.value) {
setTimeout(() => {
this.setState({
items: [],
offset: 0
}, function(){
this.searchGifs();
});
}, 10)
}
}
Thank you for all answers

React force componentDidMount

I have the following:
import React from 'react';
import axios from 'axios';
class FirstName extends React.Component {
constructor(props) {
super(props);
this.state = {
submitted: false
};
}
getName () {
var name = this.refs.firstName.value;
this.setState(function() {
this.props.action(name);
});
}
handleSubmit (e) {
e.preventDefault();
this.setState({ submitted: true }, function() {
this.props.actionID(2);
this.props.activeNav('color');
});
}
render () {
return (
<div>
<h2>tell us your first name</h2>
<form>
<input
type="text"
ref="firstName"
onChange={this.getName.bind(this)}
/>
<div className="buttons-wrapper">
<button href="#">back</button>
<button onClick={this.handleSubmit.bind(this)}>continue</button>
</div>
</form>
</div>
);
}
};
class PickColor extends React.Component {
backToPrevious (e) {
e.preventDefault();
this.props.actionID(1);
this.props.activeNav('name');
}
goToNext (e) {
e.preventDefault();
this.props.actionID(3);
this.props.activeNav('design');
this.props.displayIconsHolder(true);
}
getColorValue(event) {
this.props.color(event.target.getAttribute("data-color"));
}
render () {
var colors = ['red', 'purple', 'yellow', 'green', 'blue'],
colorsLink = [];
colors.forEach(el => {
colorsLink.push(<li
data-color={el}
key={el}
onClick={this.getColorValue.bind(this)}
ref={el}>
{el}
</li>
);
});
return (
<section>
<ul>
{colorsLink}
</ul>
<button onClick={this.backToPrevious.bind(this)}>back</button>
<button onClick={this.goToNext.bind(this)}>continue</button>
</section>
);
}
}
class ConfirmSingleIcon extends React.Component {
goBack () {
this.props.goBack();
}
confirmCaptionandIcon (event) {
var optionID = event.target.getAttribute("data-option-id"),
name = event.target.getAttribute("data-option-name");
this.props.setOptionID(optionID);
this.props.setIcon(1, name, optionID, false);
}
goNext () {
this.props.goNext();
}
render () {
console.log(this.props.currentState);
var options = [],
that = this;
this.props.iconOptionsList.forEach(function(el){
options.push(<li onClick={that.confirmCaptionandIcon.bind(that)} key={el.option} data-option-name={el.option} data-option-id={el.id}>{el.option}</li>);
});
return (
<div>
<h2>Choose your caption</h2>
<h3>
{this.props.selectedIcon}
</h3>
<ul>
{options}
</ul>
<button onClick={this.goBack.bind(this)} >back</button>
<button onClick={this.goNext.bind(this)} >confirm</button>
</div>
);
}
}
class ConfirmCaption extends React.Component {
handleClick () {
var currentState = this.props.currentState;
this.props.setIcon(currentState.icon_ID, currentState.selectedIcon, currentState.option_ID, true);
this.props.setIconVisiblity(true);
this.props.setIconListVisiblity(false);
}
render () {
console.log(this.props.currentState);
return (
<div>
<p onClick={this.handleClick.bind(this)}>confirm icon and caption</p>
</div>
);
}
}
class ChooseIcon extends React.Component {
constructor(props) {
super(props);
this.state = {
icons: [],
iconList: true,
confirmIcon: false,
confirmCaption: false,
selectedIconOptions: '',
icon_ID: '',
option_ID: '',
selectedIcon: ''
};
this.setOptionID = this.setOptionID.bind(this);
this.setIconVisiblity = this.setIconVisiblity.bind(this);
this.setIconListVisiblity = this.setIconListVisiblity.bind(this);
}
setOptionID (id) {
this.setState({ option_ID: id })
}
setIconVisiblity (onOff) {
this.setState({ confirmIcon: onOff })
}
setIconListVisiblity (onOff) {
this.setState({ iconList: onOff })
}
componentDidMount() {
var url = `http://local.tshirt.net/get-options`;
axios.get(url)
.then(res => {
this.setState({ icons:res.data.icons });
});
}
handleClick (event) {
var iconId = event.target.getAttribute("data-icon-id"),
that = this;
this.state.icons.forEach(function(el){
if(el.id == iconId){
that.setState(
{
confirmIcon: true,
iconList: false,
selectedIcon: el.name,
icon_ID: iconId,
selectedIconOptions: el.option
}
);
}
});
}
goBack () {
this.setState(
{
confirmIcon: false,
iconList: true
}
);
}
goNext () {
this.setState(
{
confirmIcon: false,
iconList: false,
confirmCaption: true
}
);
}
render () {
var icons = [];
this.state.icons.forEach(el => {
icons.push(<li data-icon-id={el.id} onClick={this.handleClick.bind(this)} key={el.name}>{el.name}</li>);
});
return (
<div>
{this.state.iconList ? <IconList icons={icons} /> : ''}
{this.state.confirmIcon ? <ConfirmSingleIcon goBack={this.goBack.bind(this)}
goNext={this.goNext.bind(this)}
setIcon={this.props.setIcon}
selectedIcon={this.state.selectedIcon}
iconOptionsList ={this.state.selectedIconOptions}
setOptionID={this.setOptionID}
currentState={this.state} /> : ''}
{this.state.confirmCaption ? <ConfirmCaption currentState={this.state}
setIcon={this.props.setIcon}
setIconVisiblity={this.setIconVisiblity}
setIconListVisiblity={this.setIconListVisiblity} /> : ''}
</div>
);
}
}
class IconList extends React.Component {
render () {
return (
<div>
<h2>Pick your icon</h2>
<ul>
{this.props.icons}
</ul>
</div>
);
}
}
class Forms extends React.Component {
render () {
var form;
switch(this.props.formID) {
case 1:
form = <FirstName action={this.props.action} actionID={this.props.switchComponent} activeNav={this.props.activeNav} />
break;
case 2:
form = <PickColor displayIconsHolder={this.props.seticonsHolder} color={this.props.colorVal} actionID={this.props.switchComponent} activeNav={this.props.activeNav} />
break;
case 3:
form = <ChooseIcon setIcon={this.props.setOptionA} />
break;
}
return (
<section>
{form}
</section>
);
}
}
export default Forms;
"ChooseIcon" is a component that will get used 3 times therefore everytime I get to it I need to bring its state back as if it was the first time.
Ideally I would need to make this ajax call everytime:
componentDidMount() {
var url = `http://local.tshirt.net/get-options`;
axios.get(url)
.then(res => {
this.setState({ icons:res.data.icons });
});
}
is there a way to manually call componentDidMount perhaps from a parent component?
React handles component lifecycle through key attribute. For example:
<ChooseIcon key={this.props.formID} setIcon={this.props.setOptionA} />
So every time your key (it can be anything you like, but unique) is changed component will unmount and mount again, with this you can easily control componentDidMount callback.
If you are using the ChooseIcon component 3 times inside the same parent component, I would suggest you to do the ajax in componentDidMount of the parent component like this (exaclty how you have in your example, in terms of code)
componentDidMount() {
var url = `http://local.tshirt.net/get-options`;
axios.get(url)
.then(res => {
this.setState({ icons:res.data.icons });
});
}
and then pass this data down to the ChooseIcon component
render() {
return (
//do your stuff
<ChooseIcon icons={this.state.icons}/>
)
}
after this you will only need to set the received props in your ChooseIconcomponent, for that you only need to change one line in it's constructor:
constructor(props) {
super(props);
this.state = {
icons: props.icons, // Changed here!
iconList: true,
confirmIcon: false,
confirmCaption: false,
selectedIconOptions: '',
icon_ID: '',
option_ID: '',
selectedIcon: ''
};
this.setOptionID = this.setOptionID.bind(this);
this.setIconVisiblity = this.setIconVisiblity.bind(this);
this.setIconListVisiblity = this.setIconListVisiblity.bind(this);
}
The parent component can use a ref to call the function directly.
However, trying to force this function feels like a smell. Perhaps lifting the state higher up the component tree would solve this problem. This way, the parent component will tell ChooseIcon what to show, and there will not be a need to call componentDidMount again. Also, I assume the Ajax call can also occur once.

Resources