#javascript #reactjs
#javascript #reactjs
Вопрос:
Я пытаюсь реорганизовать некоторые коды javascript с помощью React. Что я пытаюсь сделать, так это -> У меня есть несколько элементов с одинаковым именем класса, и я хочу иметь контроль над каждым элементом. Для этого в javascript я мог бы просто использовать функции querySelectorAll и forEach, например
<Svg>
<circle cx="100" cy="60" r="20" class="human"></circle>
<line x1="100" y1="80" x2="100" y2="120" class="human"></line>
<line x1="70" x2="100" y1="75" y2="95" class="human"></line>
<line x1="130" x2="100" y1="75" y2="95" class="human"></line>
<line x1="70" x2="100" y1="140" y2="120" class="human"></line>
<line x1="130" x2="100" y1="140" y2="120" class="human"></line>
</Svg>
const wrongLetters = [];
window.addEventListener('keydown", (e) => {
if(e.keyCode >= 65 amp;amp; e.keyCode <= 90) {
wrongLetters.push(e.key)
}
}
const humans = documentSelectorAll(".human")
humans.forEach((human, index) => {
if (index < wrongLetters.length) {
human.style.display = "block";
}
if (6 === wrongLetters.length) {
popUpContainer.style.display = "flex";
comment.innerText = "You have lost";
}
}); }
Однако я предполагаю, что в React все будет по-другому, даже если я изменю ‘class’ на ‘className’? Для этого я уже просмотрел несколько соответствующих сообщений и попытался использовать ‘ref’, но все еще не знаю точно, что делать в этом случае.
Любой совет был бы оценен.
редактировать / Что я пытаюсь сделать, так это каждый раз, когда я добавляю элемент в массив ‘wrongLetters’, будет отображаться каждый элемент в теге Svg. Для каждого элемента Svg по умолчанию установлено значение ‘display: none’ в javascript
Комментарии:
1. Обычно вы не взаимодействуете с DOM в react. Трудно дать правильный ответ, поскольку мы не знаем, что именно вы пытаетесь сделать.
2. Это действительно зависит от содержимого
do what I want here in Javascript
, можете ли вы немного уточнить, что вы хотели бы там сделать?3. В react у вас будет компонент, который отображает эти элементы, обновляя их или отображая разные элементы в соответствии с изменениями в приложении или состоянии компонента. Вам очень, очень редко требуется обращаться к DOM напрямую в react.
4. @CertainPerformance Спасибо, что я отредактировал свой пост
5. @Junyoung Посмотрите мой ответ и рабочую демонстрацию, чтобы понять, что я имею в виду.
Ответ №1:
Переведите wrongLetters
в состояние, которое будет изменено, вместо отправки в массив. Затем в React проанализируйте это состояние, чтобы определить, сколько элементов нужно скрыть. Поскольку это может охватывать все функции, которые вы ищете, нет необходимости иметь доступ к отдельным элементам DOM с помощью useRef
или querySelectorAll
:
const App = () => {
const [pressed, setPressed] = React.useState([]);
React.useEffect(() => {
window.addEventListener('keydown', (e) => {
if (!pressed.includes(e.keyCode) amp;amp; e.keyCode >= 65 amp;amp; e.keyCode <= 90) {
setPressed(pressed => [...pressed, e.keyCode]);
}
});
}, []);
return (
<svg>
<circle style={{display: pressed.length > 5 ? 'block' : 'none'}} cx="100" cy="60" r="20" stroke="black"></circle>
<line style={{display: pressed.length > 4 ? 'block' : 'none'}} x1="100" y1="80" x2="100" y2="120" stroke="black"></line>
<line style={{display: pressed.length > 3 ? 'block' : 'none'}} x1="70" x2="100" y1="75" y2="95" stroke="black"></line>
<line style={{display: pressed.length > 2 ? 'block' : 'none'}} x1="130" x2="100" y1="75" y2="95" stroke="black"></line>
<line style={{display: pressed.length > 1 ? 'block' : 'none'}} x1="70" x2="100" y1="140" y2="120" stroke="black"></line>
<line style={{display: pressed.length > 0 ? 'block' : 'none'}} x1="130" x2="100" y1="140" y2="120" stroke="black"></line>
</svg>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
line {
color: black;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
Это способ реагирования — используйте state, когда можете; избегайте прямого доступа / изменения DOM, просто заставьте рендеринг отражать состояние и изменять состояние при необходимости.
Ответ №2:
Как я уже говорил в своем комментарии, в react у вас будет компонент, который отображает эти элементы, обновляя их или отображая разные элементы в соответствии с изменениями в приложении или состоянии компонента. Вам очень, очень редко требуется обращаться к DOM напрямую в react.
Вот примерная реализация того, что я имею в виду. На codesandbox есть его живая / рабочая копия:
import React, { useEffect } from "react";
import "./styles.css";
// an array of the svg elements; the component below renders
// a subset of these according to number of attempts.
// i'm not sure this is how i'd do this in the real world
// but it's good enough for this demo.
const segments = [
<circle cx="100" cy="60" r="20" class="human"></circle>,
<line x1="100" y1="80" x2="100" y2="120" class="human"></line>,
<line x1="70" x2="100" y1="75" y2="95" class="human"></line>,
<line x1="130" x2="100" y1="75" y2="95" class="human"></line>,
<line x1="70" x2="100" y1="140" y2="120" class="human"></line>,
<line x1="130" x2="100" y1="140" y2="120" class="human"></line>
];
export default function App() {
// track the number of attempts in component state
const [attempts, setAttempts] = React.useState(0);
// handler for keydown events that for this demo
// doesn't do anything besides increment the number of attempts
const onKeyDown = React.useCallback(() => setAttempts(attempts 1), [
attempts
]);
useEffect(() => {
// when the component mounts, add the keydown listener
window.addEventListener("keydown", onKeyDown);
// when the component unmounts remove the listener
return () => window.removeEventListener("keydown", onKeyDown);
}, [onKeyDown]);
// get the visible subset of segments based on number of attempts
const visibleSegments = segments.slice(0, attempts);
// return the new markup
return (
<div className="App">
<svg viewBox="0 0 200 200" style={{ width: "300px" }}>
{visibleSegments}
</svg>
{attempts >= segments.length amp;amp; (
<div>
<div>You Lose or whatever</div>
<button onClick={() => setAttempts(0)}>Reset</button>
</div>
)}
</div>
);
}
Ответ №3:
Брат, если ты хочешь получить доступ к DOM в React JS, тебе нужно создать ссылку с помощью крючков createRef(), и тогда ты сможешь получить доступ к Dom в react как javascript
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
вы можете получить доступ к узлу, вызвав этот метод.myRef.current
const node = this.myRef.current;
Вы можете добавить одну и ту же ссылку в несколько html-элементов, и когда вы вызываете this.myRef.current, тогда ко всем элементам, которые вы помещаете в ссылку, вы можете получить доступ…