2
votes

Often when building UI the Problem arises that User Input Components are located visually outside of components owning the state.

Suppose you are building a wizard of forms with multiple steps, which has to submit a respective form on clicking the next button:

 class WizardContainer {
   render(){
     return 
       <Wizard>
         <FormContainer/>
         <NavigationContainer/>
       </Wizard>
   }
 }

 class NavigationContainer {
   currentFromContainer(){ ... }       

   render(){
     let FormContainer = currentFormContainer()
     return <FormContainer/>
   }

 class WizardContainer {
   render(){
     return 
       <Navigation title="next", onClick={...}>
    }
 }

On submit a graphql mutation with the inputs from the current Form must be fired. Ideologically the submit code for the current Form belongs into the respective Formcontainer. But the action submit Action is outside.

What would be the best way to solve such a cross component communicatioin with apollo and apollo-link-state?

Or is this something outside of apollo scope? If so, what are some react idiomatic solutions?

Redux does not solve this problem either. One can put the state of the forms to the central store, but submission is always a different action.

1

1 Answers

0
votes

Been spending the last days doing exactly this, it forced me to learn a lot about React I didn't know and was time well spent. I have a single React state in top/parent component which stores actions to be passed down to children. Biggest problem was finding a way to propagate action, React Context is good for longer distances but I mostly pass it by props.

The receiving component then has to be of class type so that it can analyze action in SCU and decide if action leads to some re-action (most commonly render).

I don't think you should copy solutions but instead do it yourself and use it to learn the depth of React, I promise you it will pay off!

Having said that you should get started with this.

  constructor() {
    super()
    this.state = {
      dispatch: this.dispatch,
      type: null,
      payload: null
    }
  }

  dispatch = (type, payload) => {
    switch (type) {
      case "user_set":
        setApolloCache({ userId: payload.userId })
   this.setState(prevState => ({
       dispatch: prevState.dispatch,
       type,
       payload
     }))
        break
   ...