#reactjs #dom #jsx
#reactjs #dom #jsx
Вопрос:
Я получаю сообщение «Не удается прочитать свойство ‘style’ null» в моем getElementById (‘password’), но оно четко определено на странице. Я новичок в react, и я предполагаю, что это запрещено или что-то в этом роде. Но я пытаюсь отобразить страницу пароля до тех пор, пока ее стиль не будет изменен на «none», что происходит в другом компоненте.
function App() {
const [loggedIn, setLoggedIn] = useState(false)
if (document.getElementById('password').style.display = "block"){
setLoggedIn(false)
} else {
setLoggedIn(true)
}
return (
<div className="app">
{ //Check if message failed
(loggedIn)
? <div> <Password /> </div>
: <div>
<Nav />
<div id="allFiles">
<FileEarth title="Earth Update"/>
<FileMars title="Mars Rover Update"/>
<HardDrvie title="ASTRO Entertainment"/>
<Folder title="Moon Pics"/>
</div>
</div>
}
</div>
);
}
export default App;
Ответ №1:
По определению на странице кажется, что у вас есть только этот компонент <Password />
, связанный с «паролем». Поскольку вы используете getElementById()
, вам нужно будет иметь возможность определять идентификатор элемента like <Password id="password" />
и передавать реквизиты в компонент, который затем назначит идентификатор как таковой.
Также p.s. у вас есть HardDrvie вместо HardDrive
Ответ №2:
Несколько вещей, которые могут вам помочь:
- Предпочтительно использовать ссылки для получения доступа к элементам DOM в React.
- При рендеринге компонента React создает представление вашего приложения в его виртуальном DOM, а затем сравнивает его с фактическим DOM, чтобы свести к минимуму дорогостоящие обновления DOM. Это означает, что в тот момент, когда вы пытаетесь использовать ‘getElementById ()`, элемент еще не был добавлен в DOM.
- Вы используете функциональный компонент, который приведет к запуску вашей встроенной логики при каждом повторном рендеринге компонента. Чтобы избежать повторного запуска этой логики, которая должна выполняться только один раз, ее следует обернуть в a
useEffect
или реже auseLayoutEffect
(см. Документы для получения дополнительной информации).
Из того, что я вижу, функция обратного вызова должна быть способна делать то, что вы хотите:
// The password component gets passed the callback function as a prop.
// In this case the callback function would be onLogin.
// When clicking the div the callback function that was provided by
// the parent will be called and the state on the parent will be
// updated.
const Password = ({ onLogin }) => {
return (
<div
onClick={onLogin}
>
Login
</div>
);
}
// Parent component.
const Parent = () => {
// Create state to store if the user is logged in or not.
const [loggedIn, setLoggedIn] = React.useState(false);
// Create callback function to pass to the Password component.
// useCallback ensures that the function is only recreated when
// a variable in the dependency array is updated.
// The dependency array uses a reference compare to check for changes.
const onLogin = React.useCallback(() => {
setLoggedIn(true);
}, [setLoggedIn] /* Dependency Array - recreate on setLoggedIn change */ );
return (
<>
<div>
{/* Write out loggedIn value for debugging. */}
{ loggedIn ? "Logged In" : "Not Logged In" }
</div>
{/* Conditionally render password component passing onLogin */}
{ !loggedIn amp;amp; <Password onLogin={onLogin} /> }
</>
)
}
Комментарии:
1. Хороший! Хотя я не думаю, что useCallback здесь необходим на 100% и может фактически снизить производительность, добавив его. Вместо этого, вероятно, было бы проще и эффективнее просто иметь
const handleLogin = () => setLoggedIn(true)
. Вот несколько статей, в которых вы можете прочитать больше об этом: atomizedobjects.com/blog/react /… и kentcdodds.com/blog/usememo-and-usecallback