@Ostic
Программист - любитель

Как обойти ошибку с типом never?

Здравствуйте.
Вот пример:
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>
  )
}

говорит, что нет у типа never св-ва classList...
сначала ругался также на null, я добвил if, теперь ругается на never, пробовал try-catch - не помогает.
чего делать-то? подскажите
  • Вопрос задан
  • 304 просмотра
Решения вопроса 2
rockon404
@rockon404 Куратор тега React
Frontend Developer
В React разработке приветствуется подход с изменением состояния:
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>}
      </>
    );
  }
}

или:
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>}
    </>
  );
};


Можно еще для подобных кейсов кастомный хук написать:
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];
};

и тогда:
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>;
};
Ответ написан
@forspamonly2
про то, как это вообще лучше в реакте делать, вам написал Антон Спирин, а конкретно проблему с тайпскриптовскими типами решить можно параметризовав тип референса:
const buttonEl = useRef<HTMLButtonElement>();
buttonEl.current.classList.add("is-hide");
return <button ref={buttonEl}>lioih</button>;
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы