Fcoder
Fcoder

Reputation: 9226

Updating state of a component from another component in React

In a React project I had a components named Auth.jsx that manage authentication and routing. Like this:

let ComponentToShow;
let path="/";
let isSMSSent = false;

function Auth(){

       if(isSMSSent){
          let args = {
             onBackClick:handleBackClick,
           }
           path = "/receive";
           ComponentToShow = <CheckSMSCode args={args} />;
       else{
            let args = {
                onClick:handleSendSMSClick,
            }

            path = "/send";
            ComponentToShow = <SMSAuth args={args} />;

       }

       return(
        <Router>
        <Redirect to={path} />
          <Switch>

            <Route path="/send">
                {ComponentToShow}
            </Route>

            <Route path="/receive">
                {ComponentToShow}
            </Route>

          </Switch>
      </Router>
    );
}

Now, What I want to do is that, if there is an error in the Auth.jsx component, Show an error message in the SMSAuth.jsx component. Because the brain of the app is Auth.jsx, I handle errors here, but I want to show errors inside each component that Im showing. In fact i want to update state in the another component and the UI updates.

I googled this and some people says Redux can help this. but i don't want to use Redux and stick to pure React. What I have to do to solve my problem? using Redux is mandatory and Im thinking wrong about that?

What Im thinking about that is connecting two component via props and creating a reference to the main component to use resources, but I don't know how to do that. I know using React.context can have shared values between components but changing in the shared value doesn't change the UI because state not updated.

Upvotes: 0

Views: 324

Answers (2)

ali erenkara
ali erenkara

Reputation: 79

Maybe use callback function like this ;

const [isSMSSent, setisSMSSent] = useState(false);

setSmsSent = (value) => {setisSMSSent(value)}

<CheckSMSCode args={args} setSmsSent={setSmsSent} />

Upvotes: 1

HMR
HMR

Reputation: 39320

You can use context, here is an example using counter

const CounterContext = React.createContext();
const CounterProvider = ({ children }) => {
  const [count, setCount] = React.useState(0);
  const up = React.useCallback(
    () => setCount((count) => count + 1),
    []
  );
  const down = React.useCallback(
    () => setCount((count) => count - 1),
    []
  );
  return (
    <CounterContext.Provider
      value={{
        count,
        up,
        down,
      }}
    >
      {children}
    </CounterContext.Provider>
  );
};

const Counter = React.memo(function Counter() {
  const { up, down, count } = React.useContext(
    CounterContext
  );
  return (
    <div>
      <div>
        <button onClick={up}>+</button>
      </div>
      <div>{count}</div>
      <div>
        <button onClick={down}>-</button>
      </div>
    </div>
  );
});

const App = function () {
  return (
    <CounterProvider>
      <Counter />
    </CounterProvider>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

Your component probably doesn't re render because you are mutating some value that is not managed in any React or Redux state. The counter works because count comes from React state and is not mutated when changed.

Upvotes: 1

Related Questions