Перерисовка компонента на верхнем уровне

#javascript #reactjs

Вопрос:

Я получаю данные с сервера в компоненте верхнего уровня, и когда я получаю какие-то конкретные данные, я хочу повторно отправить компонент приложения, чтобы в нем были эти новые данные, поступившие с сервера, но я не могу придумать, как, потому что я не могу использовать, например, крючки на компоненте верхнего уровня. Я знаю, что я мог бы просто переместить всех своих слушателей в компонент приложения и просто делать там все, что нужно, но мне не нравится, что он отправит в 4 раза больше запросов с сервера, потому что он повторяется в каждом состоянии.

Поэтому я хотел спросить, есть ли возможность включить моих слушателей в компонент верхнего уровня и просто повторно включить дочерние компоненты.

Вот мой код компонента верхнего уровня

 import React from 'react';
import ReactDOM from 'react-dom';
import { GlobalStyle } from './components/global_styles';
import App from './components/App';

const ws = new WebSocket("ws://localhost:3001");
var token = JSON.parse(localStorage.getItem('loginToken') || '{}');

ws.onmessage = ({ data }) => {
  const parsedData = JSON.parse(data)

  switch (parsedData.type) {
    case 'login-success':
      console.log('logged in');
      token = parsedData.user;
      break;

    case 'login-fail':
      console.log(parsedData.error);
      break;
  }
};

ReactDOM.render(
  <React.StrictMode>
    <GlobalStyle />
    <App ws={ws} token={token} />
  </React.StrictMode>,
  document.getElementById('root')
);
 

В частности, я говорю о переменной «токен», всякий раз, когда она меняется, она должна повторно передавать компонент приложения.

Комментарии:

1. почему бы вам не использовать глобальный менеджер состояний, такой как redux? можно достичь ваших ожиданий без глобального менеджера состояний, но на самом деле использование глобального менеджера состояний помогает и упрощает вашу реализацию.

2. в качестве общего совета: использование крючков react позволит контролировать эти побочные эффекты и даст вам возможность повторно визуализировать ваш компонент по мере необходимости.

3. Теперь ws и token за пределами любых компонентов react react не знает, когда он обновляется.

Ответ №1:

Если вы хотите, чтобы изменения token вызвали повторный запрос, его необходимо сделать переменной состояния.

Один из шаблонов, который может соответствовать вашим потребностям, — это использование Context , которое сохраняет токен и использует его в вашем App компоненте

Я бы предположил, что это будет что-то вроде этого

 const TokenContext = React.createContext()

export const TokenProvider = ({children}) => {
    const [token, setToken] = useState(JSON.parse(localStorage.getItem('loginToken') || '{}'));

    useEffect(() => {
      const ws = new WebSocket("ws://localhost:3001");
      ws.onmessage = ({ data }) => {
  const parsedData = JSON.parse(data)

  switch (parsedData.type) {
    case 'login-success':
      console.log('logged in');
      setToken(parsedData.user);
      break;

    case 'login-fail':
      console.log(parsedData.error);
      break;
  }
};
    return () => {/*whatever you need to do for cleanup, e.g. closing the connection*/}
     },[]);


    return (<TokenContext.Provider value={token}>{children}</TokenContext.Provider>)



}


export const useToken = () => useContext(TokenContext)

 

В свой код верхнего уровня добавьте (после импорта, конечно)

 ReactDOM.render(
  <React.StrictMode>
    <TokenProvider>
    <GlobalStyle />
    <App ws={ws} token={token} />
    </TokenProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

 

И теперь вы можете использовать useToken крючок везде, где вам token это нужно const token = useToken()

В качестве альтернативы вы можете использовать глобальный менеджер состояний, такой как Redux или MobX, или один из тысячи других, которые существуют для React, и я больше не могу отслеживать

Ответ №2:

внутри вашего App компонента просто используйте useEffect крючок с маркером в качестве зависимости, как

useEffect(()=>{ /* token changed do something */ },[token])