I would like to pass the both states as the result of getSettings method in Settings component to Add component. Is there any way to do that without copying the method to the other component?
Thank you
Settings component
export class Settings extends Component {
constructor(props) {
super(props);
this.state = {
languages: [],
currencies: []
};
}
getSettings() {
fetch('/settings', {
method: 'get',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then( ... )
.then(json => {
this.setState({
currencies: json.currencies,
languages: json.languages
});
})
}
}
Add component
export class Add extends Component {
displayName = Add.name
constructor(props) {
super(props);
this.state = {
languages: [],
currencies: []
};
}
I can think of two ways where you can share your states in Settings
.
you can simply pass the state into this.props.children
or this.props.render
.
class Settings extends Component {
state = {
languages: [],
currencies: []
};
getSettings = () => {
// fetch('/settings', {
// method: 'get',
// headers: {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// }
// })
// .then( ... )
// .then(json => {
// this.setState({
// currencies: json.currencies,
// languages: json.languages
// });
// })
this.setState({
currencies: ["Dollar", "Euro", "Won"],
languages: ["English", "French", "Korean"]
});
};
componentDidMount() {
this.getSettings();
}
render() {
return <div>{this.props.children(this.state)}</div>;
}
}
And use it like this.
const renderComponents = (currencies, languages) => {
const currencyItems = currencies.map(currency => (
<li key={currency}>{currency}</li>
));
const languageItems = languages.map(language => (
<li key={language}>{language}</li>
));
return (
<div>
<h3>currencies</h3>
<ul>{currencyItems}</ul>
<hr />
<h3>languages</h3>
<ul>{languageItems}</ul>
</div>
);
};
const AppChildAsFunction = () => (
<div>
<h2>Using Child as Function</h2>
<Settings>
{({ currencies, languages }) => renderComponents(currencies, languages)}
</Settings>
</div>
);
Create and export new Settings provider, and consumer
SettingsContext.js
import React, { Component } from "react";
const defaultValue = {
currencies: ["Dollar", "Euro", "Won"],
languages: ["English", "French", "Korean"]
};
const { Provider, Consumer: SettingsConsumer } = React.createContext(
defaultValue
);
class SettingsProvider extends Component {
state = {
languages: [],
currencies: []
};
render() {
return <Provider value={this.state}>{this.props.children}</Provider>;
}
}
export { SettingsProvider, SettingsConsumer };
And the usage is about the same
App.js
import { SettingsProvider, SettingsConsumer } from "./SettingsContext";
...
const AppWithContext = () => (
<div>
<h2>Using Context API</h2>
<SettingsConsumer>
{({ currencies, languages }) => renderComponents(currencies, languages)}
</SettingsConsumer>
</div>
);
You can just pick and choose whichever one suits your taste.
Working Demo on CodeSandBox.
High order component is good for this case. First you create method withSetting
.
export const withSetting = (Component) => class extends Component {
constructor(props) {
super(props);
this.state = {
languages: [],
currencies: []
};
}
getSettings() {
fetch('/settings', {
method: 'get',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then( ...)
.then(json => {
this.setState({
currencies: json.currencies,
languages: json.languages
});
})
}
render() {
return <Component getSetting={this.getSetting} {...this.state} />
}
}
And in Add
Component. You can call this.props.getSetting
or use this.props. languages
and this.props. currencies
import {withGetSetting} from './withGetSetting'
class Add extends React.Component {...}
export default withSetting(Add)
You can read about HOC here https://reactjs.org/docs/higher-order-components.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With