O
O
Ostic2019-06-01 20:01:05
typescript
Ostic, 2019-06-01 20:01:05

How to get around the never type error?

Hello.
Here is an example:

const MyComponent: React.FC = () => {
  const buttonEl = useRef(null);
  useEffect( ()=>{
    function scrollHandler(): void { 
      var buttonHtmlEl: HTMLElement | null = buttonEl.current;
      if ( buttonHtmlEl ) {
        window.pageYOffset > 50 ? buttontHtmlEl.classList.remove('is-hide') : buttonHtmlEl.classList.add('is-hide')
// Подчеркивает здесь classList и говорит, что у типа never
// нет св-ва classList
      } else {
        console.error('...');
      }
    }
    window.addEventListener('scroll', scrollHandler);
      return ()=>{
        window.removeEventListener('scroll', scrollHandler);
      }        
    }
  )
  return (
    <button ref={bttEl} onClick={toTop}>lioih </button>
  )
}

says that the never type has no classList properties...
at first it also cursed at null, I added if, now it curses at never, tried try-catch - it doesn't help.
what to do? tell

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2019-06-02
@Ostic

In React development, the stateful approach is welcome:

interface State {
  shouldShowBtn: boolean;
}

class MyComponent extends React.Component<null, State> {
  state = {
    shouldShowBtn: true,
  };

  componentDidMount() {
    window.addEventListener('scroll', this.scrollHandler);
  }

  scrollHandler = () => {
    const { shouldShowBtn } = this.state;

    if (window.pageYOffset > 50 && shouldShowBtn) {
      this.setState({ shouldShowBtn: false });
    } else if (window.pageYOffset <= 50 && !shouldShowBtn) {
      this.setState({ shouldShowBtn: true });
    }
  };

  componentWillUnmount() {
    window.removeEventListener('scroll', this.scrollHandler);
  }

  render() {
    return (
      <>
       {this.state.shouldShowBtn && <button>lioih </button>}
      </>
    );
  }
}

or:
const MyComponent: React.FC = () => {
  const [shouldShowBtn, setShouldShowBtn] = useState(true);
  
  const context = useMemo(() => ({ shouldShowBtn }), []);

  useEffect(() => {
    context.shouldShowBtn = shouldShowBtn;
  }, [shouldShowBtn]);

  useEffect(() => {
    const scrollHandler = () => {
      if (window.pageYOffset > 50 && context.shouldShowBtn) {
        setShouldShowBtn(false);
      } else if (window.pageYOffset <= 50 && !context.shouldShowBtn) {
        setShouldShowBtn(true);
      }
    };

    window.addEventListener('scroll', scrollHandler);
    
    return () => {
      window.removeEventListener('scroll', scrollHandler);
    };
  }, []);
  
  return (
    <>
     {shouldShowBtn && <button>lioih </button>}
    </>
  );
};

You can also write a custom hook for such cases:
const useGetState = (initialState: any) => {
  const [state, _setState] = useState(initialState);
  const context = useMemo(() => ({ state }), []);
  const getState: any = useCallback(() => context.state, []);
  const setState = useCallback((state) => {
    context.state = state;
    _setState(state);
 }, []);

  return [getState, setState];
};

and then:
const MyComponent: React.FC = () => {
  const [getShouldShowBtn, setShouldShowBtn] = useGetState(true);

  useEffect(() => {
    const scrollHandler = () => {
      console.log(window.pageYOffset, getShouldShowBtn());
      if (window.pageYOffset > 50 && getShouldShowBtn()) {
        setShouldShowBtn(false);
      } else if (window.pageYOffset <= 50 && !getShouldShowBtn()) {
        setShouldShowBtn(true);
      }
    }
    window.addEventListener("scroll", scrollHandler);
    return () => {
      window.removeEventListener("scroll", scrollHandler);
    };
  }, []);
  return <div>{getShouldShowBtn() && <button>lioih </button>}</div>;
};

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question