Reputation: 1001
I have created a context (CharacterContext) which exports class CharacterProvider, which itself passes to the consumers several objects in the state. I would like to also pass a REST call function getCharacter. I was thinking about passing it like this:
export class CharacterProvider extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
...
getCharacter: this.getCharacter(),
}
}
getCharacter = (id) => {
console.log("Getting the character...")
CharacterDataService.getCharacterById(id)
.then(
response => {
console.log(response);
this.setState({
name: response.data.username,
...
});
}
)
}
render() {
return (
<CharacterContext.Provider
value={this.state}>
{
this.props.children
}
</CharacterContext.Provider>
)
}
export const CharacterConsumer = CharacterContext.Consumer
However I guess this would only fire the function and pass the result. What is the correct way to pass the function? So far the element has received the function in the props like this:
export default class Loader extends React.Component {
constructor(props) {
super(props);
this.state = {
names: [/* filled by an API call */]
}
....
render() {
return (
<div className="row mt-3">
<div className="col"></div>
{
Object.values(this.state.names).map( (name) => {
return(
<div className="col-1" key={name}>
<button className="btn btn-info" onClick={() =>
this.props.getCharacter(Object.keys(this.state.names).find(key => this.state.names[key] === name))} key={name}>
{name}
</button>
</div>
)})
}
<div className="col"></div>
</div>
)
}
}
I would like to pass the function from the Context as it will be used in several different components too. I have used the contest to pass values succesfully but I am still looking for the correct way to pass functions, and I have found not tutorial that would really help me with that so far.
Sorry if the code is wobbly, I have just recently started with ReactJS and JS itself.
Edit:
I am passing the provider like this:
App.js
...
render() {
return (
<div className="App container-fluid">
<CharacterProvider>
<Loader/>
</CharacterProvider>
...
Upvotes: 2
Views: 10117
Reputation: 281686
You aren't using context correctly. You need to render the Provider
and wrap it in the hierarchy
export class CharacterProvider extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
...
getCharacter: this.getCharacter(),
}
}
getCharacter = (id) => {
console.log("Getting the character...")
CharacterDataService.getCharacterById(id)
.then(
response => {
console.log(response);
this.setState({
name: response.data.username,
...
});
}
)
render() {
return (
<CharacterContext.Provider value={this.state}>{children}</CharacterContext.Provider>
)
}
}
export const CharacterConsumer = CharacterContext.Consumer
Not you render this CharacterProvider
in the hierarchy like
return (
<CharacterProvider>
<Loader/>
</CharacterProvider>
)
Now you need to specify the contextTypes for Loader and use the function from this.context
export default class Loader extends React.Component {
static contextTypes = CharacterContext
constructor(props) {
super(props);
this.state = {
names: [/* filled by an API call */]
}
....
render() {
return (
<div className="row mt-3">
<div className="col"></div>
{
Object.values(this.state.names).map( (name) => {
return(
<div className="col-1" key={name}>
<button className="btn btn-info" onClick={() =>
this.context.getCharacter(Object.keys(this.state.names).find(key => this.state.names[key] === name))} key={name}>
{name}
</button>
</div>
)})
}
<div className="col"></div>
</div>
)
}
}
Upvotes: 4