#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])