Home > Mobile >  React - How to change a string value with chain conditional (ternary) operator while having a defaul
React - How to change a string value with chain conditional (ternary) operator while having a defaul

Time:09-28

I am not sure if the question title is the best, but... I have a button with the text "Click" and would like the text to change the base of the feaching response. If it's loading to show "Sending" if it's successful to show "Success" if it failed to show "Error".

I tried using conditional ternary but I can't make it have a default value ("Click") and then change it back to the default after the success or error message shows.

In the code below I simulated the feaching just for the purpose of the demo. Also here is the codeSendBox if it helps.

export default function App() {
  const [isSending, setIsSending] = useState(false);
  const [success, setSuccess] = useState(null);

  const x = 1;

  const simulateFetching = () => {
    setIsSending(true);
    setTimeout(() => {
      if (x === 1) {
        setSuccess(true);
        setIsSending(false);
      } else if (x === 0) {
        setSuccess(false);
      }
    }, 500);
  };

  return (
    <button onClick={simulateFetching}>
      {"Click" && isSending ? "Sending..." : success ? "Success" : "Error"}
    </button>
  );
}

CodePudding user response:

As I think you are just testing your code here is a fast solution:

export default function App() {
  const [isSending, setIsSending] = useState(false);
  const [success, setSuccess] = useState(null);

  const x = 0;

  const simulateFetching = () => {
    setIsSending(true);
    setTimeout(() => {
      if (x === 1) {
        setSuccess(true);
        setIsSending(false);
      } else if (x === 0) {
        setSuccess(false);
      }
    }, 500);

    setTimeout(() => {
      setSuccess(null);
      setIsSending(false);
    }, 2000);
  };

  return (
    <button onClick={simulateFetching}>
      {isSending && success === null
        ? "Sending"
        : success
        ? "Succes"
        : isSending && !success
        ? "Error"
        : "Click"}
    </button>
  );
}

But if your goal is only to display the button text then:

export default function App() {
  const [status, setStatus] = useState("Click");
  
  const x = 0;

  const simulateFetching = () => {
    setStatus('Sending');
    setTimeout(() => {
      if (x === 1) {
        setStatus('Success');
      } else if (x === 0) {
        setStatus('Error');
      }
    }, 500);

    setTimeout(() => {
      setStatus('Click');
    }, 2000);
  };

  return (
    <button onClick={simulateFetching}>
      {status}
    </button>
  );
}

CodePudding user response:

For what it's worth, I don't like the coding pattern you're using with all of those ternaries. It gets messy and hard to read.

Your React components re-render when anything in the Component changes, so I like to deterministically render values like this.

For example:

const Component = () => {
let buttonText = 'Send'
if (myFunc.isLoading) buttonText = 'Sending...'
if (myFunc.isSuccess) buttonText = 'Sent'

return (<>
<button>{buttonText}</button>
</>)
}

If you use a nice async package like react-query or something like that, those async states like isLoading, isError, etc. will come out of the box.

That's the way to go.

  • Related