Reputation: 131
I have some big function methods in my react component and I want to put those functions to separate files, import them with es6
modules system.
The problem is that inside those methods I'm changing the state of the parent component with setState
method.
What is the best way to use function in separate file, import this function and use with simple setstate method?
See the fetchProducts
method. I want to import this method from separate file
Here is the code:
import React from 'react'
import Header from '../components/Header'
class Main extends React.Component {
constructor(props) {
super(props)
this.state = {
firstDetected: false,
detected: false,
products: [],
selectedProduct: null,
premiumImage: null,
productImages: [],
productPrice: null,
dataFromServer: null,
default_gender: null,
bgImage: null,
productsExtension: null,
mediaCdn: null,
fade: false,
hello: false,
helloEnd: false,
collection: false,
collectionEnd: false,
capturedImage: null,
imageReady: false,
gender: null,
waitForEnding: true
}
}
componentWillMount() {
this.fetchProducts(1)
}
fetchProducts = (init) => {
auth.fetch(`${baseUrlTest}/products/get-user-products?init=${init}`)
.then(res => {
if (Object.keys(res).length) {
console.log(res)
const productsExtension = res['products.extension']
const mediaCdn = res['media.cdn']
const randomProduct = randomize(res['products'])
this.setState({
dataFromServer: res,
products: res.products,
selectedProduct: randomProduct,
default_gender: res.default_gender,
bgImage: res['background.image'],
productsExtension: productsExtension,
mediaCdn: mediaCdn,
gender: res.default_gender,
premiumImage: mediaCdn + randomProduct.image + '.' + productsExtension.find(k => k === 'jpg'),
productPrice: randomProduct.price,
productImages: res.products.filter((prod) => {
return prod.gender === res.default_gender
}).map((prod) => {
return prod
})
})
console.log(res.products)
}
})
}
}
Upvotes: 1
Views: 7614
Reputation: 867
First you bind your function scope to its owner component scope.
class Main extends React.Component {
constructor(props) {
// {...}
this.fetchProducts = this.fetchProducts.bind(this);
}
}
Then you export your component instead of its function, which will allow you to access this function as well as the other members of your component.
export default class Main extends React.Component
Then import it at the beginning of your other scripts/components/tests
import Main from './Main';
And use its function as you see fit
let state = {};
Main.fetchProducts(state);
Or you could just export your function, in case that's the only part of your component you want to access.
class Main extends React.Component {
// {...}
export fetchProducts {
// {...}
}
}
And then import it in the other scripts
import fetchProducts from './Main';
Upvotes: 0
Reputation: 96
Solution without Redux
fetchProduct
function as a moduleMain
componentfetchProduct
into our componentWe can't use arrow function for
fetchProduct.js
As stated in YDKJS - "ES6 arrow-functions use lexical scoping for this binding, which means they adopt the this binding (whatever it is) from its enclosing function call."
fetchProducts.js
// Export the function as a module
export default function fetchProducts(init) {
auth.fetch(`${baseUrlTest}/products/get-user-products?init=${init}`)
.then(res => {
if (Object.keys(res).length) {
console.log(res)
const productsExtension = res['products.extension']
const mediaCdn = res['media.cdn']
const randomProduct = randomize(res['products'])
this.setState({
dataFromServer: res,
products: res.products,
selectedProduct: randomProduct,
default_gender: res.default_gender,
bgImage: res['background.image'],
productsExtension: productsExtension,
mediaCdn: mediaCdn,
gender: res.default_gender,
premiumImage: mediaCdn + randomProduct.image + '.' + productsExtension.find(k => k === 'jpg'),
productPrice: randomProduct.price,
productImages: res.products.filter((prod) => {
return prod.gender === res.default_gender
}).map((prod) => {
return prod
})
})
console.log(res.products)
}
})
}
Main.js
import React from 'react'
import Header from '../components/Header'
// Import the exported function from fetchProduct.js
import fetchProducts from "../middleware/fetchProduct.js"
class Main extends React.Component {
constructor(props) {
super(props)
this.state = {
firstDetected: false,
detected: false,
products: [],
selectedProduct: null,
premiumImage: null,
productImages: [],
productPrice: null,
dataFromServer: null,
default_gender: null,
bgImage: null,
productsExtension: null,
mediaCdn: null,
fade: false,
hello: false,
helloEnd: false,
collection: false,
collectionEnd: false,
capturedImage: null,
imageReady: false,
gender: null,
waitForEnding: true
}
}
componentWillMount() {
// Assign fetchProducts into your Component
this.fetchProducts = fetchProducts.bind(this);
// Call fetchProduct() inside your Component
this.fetchProducts();
}
}
Upvotes: 1
Reputation: 4464
You can simply return the data from your function then set this data in the state of any component :
fetchProducts = init => {
return auth
.fetch(`${baseUrlTest}/products/get-user-products?init=${init}`)
.then(res => {
if (Object.keys(res).length) {
console.log(res);
const productsExtension = res['products.extension'];
const mediaCdn = res['media.cdn'];
const randomProduct = randomize(res['products']);
return {
dataFromServer: res,
products: res.products,
selectedProduct: randomProduct,
default_gender: res.default_gender,
bgImage: res['background.image'],
productsExtension: productsExtension,
mediaCdn: mediaCdn,
gender: res.default_gender,
premiumImage:
mediaCdn +
randomProduct.image +
'.' +
productsExtension.find(k => k === 'jpg'),
productPrice: randomProduct.price,
productImages: res.products
.filter(prod => {
return prod.gender === res.default_gender;
})
.map(prod => {
return prod;
})
};
}
throw new Error('res has no data');
});
};
Then use it in a component :
componentDidMount() {
fetchProducts('initVar').then(res => this.setState(res)).catch(err => console.log(err));
}
Upvotes: 0