skip to Main Content

I am trying to set a boolean value using a setEditMode function but unfortunately, I am encountering with a type error while invoking the component in index.tsx file.

The error is Type 'boolean' is not assignable to type '(editMode: boolean) => void'.ts(2322)

Here is the Sandbox link

The error can be checked in the index.tsx file.
Can anybody guide me with the correct path Why is it so and what is the best way to solve it.

2

Answers


  1. As the comments mentioned you are passing a boolean to a prop that expects a function.
    You can avoid that by passing the editMode value instead like so.

    root.render(
      <React.StrictMode>
        <App initialEditMode={false} />
      </React.StrictMode>
    );
    

    And then for what I believe is the functionality you want you can modify the App.js to be like this

    import React from "react";
    import "./styles.css";
    
    interface Props {
      initialEditMode: boolean;
    }
    
        export default function App({ initialEditMode }: Props) {
          const [editMode, setEditMode] = React.useState(initialEditMode);
          const openEditMode = () => {
            setEditMode(true);
          };
          return !editMode && <div onClick={openEditMode}>Edit</div>;
        }
    

    This would use the initial edit value from your index file to create a new state. And then clicking on the edit button would update the editMode state to true

    Login or Signup to reply.
  2. I would avoid props in the App component. Instead, I would create an EditableComponent that takes these props. Just keep track of the state in App or a context/store. The internal component can handle local updates to the value.

    import * as React from "react";
    import EditableComponent from "./EditableComponent";
    import "./styles.css";
    
    export default function App() {
      const [editMode, setEditMode] = React.useState(false);
      const [value, setValue] = React.useState("Hello World!");
    
      return (
        <EditableComponent
          editMode={editMode}
          setEditMode={setEditMode}
          updateValue={setValue}
          value={value}
        />
      );
    }
    

    The following component takes an edit mode and a value. The component itself updates the local value, and upon saving, will update the value in the App. I wrapped the <input> in a form so that he Enter key will trigger the update (if you do not wish to click the button).

    I also added a cancel action that reverts the value back to the original.

    import * as React from "react";
    
    export type EditableComponentProps = {
      editMode: boolean;
      setEditMode: (editMode: boolean) => void;
      value: string;
      updateValue: (value: string) => void;
    };
    
    export default function EditableComponent(props: EditableComponentProps) {
      const { editMode, setEditMode, updateValue, value } = props;
    
      const [localValue, setLocalValue] = React.useState(value);
    
      React.useEffect(() => {
        setLocalValue(value);
      }, [value]);
    
      const updateLocalValue = React.useCallback(
        (event: React.ChangeEvent<HTMLInputElement>): void => {
          setLocalValue(event.target.value);
        },
        []
      );
    
      const openEditMode = React.useCallback(() => {
        setEditMode(true);
      }, [setEditMode]);
    
      const closeEditMode = React.useCallback(
        (e: React.FormEvent) => {
          e.preventDefault();
          const form: HTMLFormElement = e.target as HTMLFormElement;
          const data: FormData = new FormData(form);
          const newValue = data.get("localValue")?.toString() ?? "";
          setEditMode(false);
          updateValue(newValue);
        },
        [setEditMode, updateValue]
      );
    
      const revertValue = React.useCallback(() => {
        setEditMode(false);
        setLocalValue(value);
      }, [setEditMode, value]);
    
      // Render the "edit"
      if (editMode) {
        return (
          <form onSubmit={closeEditMode}>
            <input
              type="text"
              name="localValue"
              value={localValue}
              onInput={updateLocalValue}
            />
            <br />
            <br />
            <button type="submit">Save Changes</button>
            <button type="button" onClick={revertValue}>
              Cancel
            </button>
          </form>
        );
      }
    
      return (
        <>
          <p>{value}</p>
          <button type="button" onClick={openEditMode}>
            Edit
          </button>
        </>
      );
    }
    

    Snippet

    Here is a working snippet. Note that it’s JSX rather than TSX, so types will not be defined, but the principle business logic remains.

    const { Fragment, useCallback, useEffect, useState } = React;
    
    const EditableComponent = (props) => {
      const { editMode, setEditMode, updateValue, value } = props;
      const [localValue, setLocalValue] = useState(value);
    
      useEffect(() => {
        setLocalValue(value);
      }, [value]);
    
      const updateLocalValue = useCallback((event) => {
        setLocalValue(event.target.value);
      }, []);
    
      const openEditMode = useCallback(() => {
        setEditMode(true);
      }, [setEditMode]);
    
      const closeEditMode = useCallback((e) => {
        e.preventDefault();
        const form = e.target;
        const data = new FormData(form);
        const newValue = data.get("localValue") || "";
        setEditMode(false);
        updateValue(newValue);
      }, [setEditMode, updateValue]);
    
      const revertValue = useCallback(() => {
        setEditMode(false);
        setLocalValue(value);
      }, [setEditMode, value]);
    
      // Render the "edit"
      if (editMode) {
        return (
          <form onSubmit={closeEditMode}>
            <input
              type="text"
              name="localValue"
              value={localValue}
              onInput={updateLocalValue}
            />
            <br />
            <br />
            <button type="submit">Save Changes</button>
            <button type="button" onClick={revertValue}>
              Cancel
            </button>
          </form>
        );
      }
    
      return (
        <Fragment>
          <p>{value}</p>
          <button type="button" onClick={openEditMode}>
            Edit
          </button>
        </Fragment>
      );
    }
    
    const App = () => {
      const [editMode, setEditMode] = useState(false);
      const [value, setValue] = useState("Hello World!");
    
      return (
        <EditableComponent
          editMode={editMode}
          setEditMode={setEditMode}
          updateValue={setValue}
          value={value}
        />
      );
    };
    
    ReactDOM
      .createRoot(document.getElementById("root"))
      .render(<App />);
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search