diegohaz/constate

child component is not rerendering.

viperfx opened this issue · 3 comments

So I have

import createContainer from "constate";
export const Form = createContainer(useFormState, value => [value.values]);
function formReducer(state, action) {
  switch (action.type) {
    case 'add-text':
      let newState = {
        ...state,
        report_fields: [...state.report_fields, {value:null, type:'text'}]
      }
      return newState;
    default:
      throw new Error();
  }
}

function useFormState({ initialValues = {} } = {}) {
  const [state, dispatch] = useReducer(formReducer, initialValues);
  return { state, dispatch };
}
<Form.Provider initialValues={{report_fields: props.report_fields, report: props.report, team: props.team}}>
   <Wizard/>
</Form.Provider>

The Wizard does this

function Wizard() {
  const { step, next, previous } = useContext(Step.Context);
  const steps = [StepOneQuestions, StepTwoMembers];
  return React.createElement(steps[step]);
}

And in StepTwo

export default function StepOneQuestions (props) {
    const {state, dispatch} = useContext(Form.Context);
    
    return ( .... )
}

That StepOneQuestions is not re-rendering when dispatching an action such as add-text

Hi @viperfx

export const Form = createContainer(useFormState, value => [value.values]);
                                                                  ^

useFormState doesn't return .values. You should probably use [value.report_fields, value.report, value.teams] or don't pass anything there.

Edit:

This is the correct usage for your case:
export const Form = createContainer(useFormState, ({ state }) => [...state.report_fields, state.report, state.team]);

Nevermind, you have deep objects and arrays. Computing changes on your state would be probably more expensive than re-rendering components.

hey @diegohaz thanks for the quick reply. I change to export const Form = createContainer(useFormState); and it worked as expected.

I realise now I was using your wizard example on the repo, but I change the hook return signature.

So leaving it blank - does that have any impact?

So if I called my state, values in my return for hooks such as { values, dispatch } that would have worked?

If you leave it blank, consumers will re-render whenever the Provider re-renders (even when its state hasn't changed). For most apps it shouldn't be a problem though.

See https://github.com/diegohaz/constate#creatememoinputs