#javascript #reactjs #state #jsx #react-props
#javascript #reactjs #состояние #jsx #react-props
Вопрос:
Я бы хотел, чтобы мой код обновлял переменную «currentPage» для файловых функций (App.js и startMenu.js ). В настоящее время я могу сделать это с помощью состояний, используя только App.js , но хотел бы упростить свой код таким образом, чтобы я мог использовать другие файлы * .js в каталоге. Прямо сейчас startMenu.js звонит из App.js в форме App.toMainMenu и App.toLevelBuilder, но он не обновляет переменную состояния, «currentPage» onClick, как я бы хотел.
App.js:
import React, {useState} from "react";
import startMenu from "./startMenu";
import levelBuilder from "./levelBuilder";
function App(){
const[currentPage, setPage] = useState("start")
function toMainMenu(){
setPage(prevPage => "main")
}
function toLevelBuilder(){
setPage(prevPage => "levels")
}
function renderSwitch(param) {
switch(param) {
case 'levels':
return levelBuilder();
default:
return startMenu();
}
}
return (
<div >
<span>{currentPage}</span>
{renderSwitch(currentPage)}
</div>
)
}
export default App;
startMenu.js
import React, {useState} from "react";
import levelBuilder from "./levelBuilder";
import App from "./App";
function startMenu() {
return(
<div className="container">
{/* start menu */}
<img id = "scan_logo"src={process.env.PUBLIC_URL '/scanlogo.png'} />
<button id="menuStart" onClick={App.toMainMenu}> START </button>
<button id="menuLevel" onClick={App.toLevelBuilder}> LEVEL BUILDER </button>
</div>
)
}
export default startMenu;
Я думал, что мне нужно использовать props, но в качестве React.js новичок, это меня немного смущает. Любые идеи будут с благодарностью!
Спасибо!
Комментарии:
1. Есть ли причина, по которой вы используете функциональные компоненты вместо компонентов класса?
2. Вы могли бы поместить свой код в codesandbox для облегчения
3. Функциональные компоненты и хуки — это правильный путь.
4. Я использую функциональные компоненты, поскольку у меня сложилось впечатление, что нельзя использовать состояния с компонентами класса
5. Если вы хотите, чтобы вашим состоянием управляли все ваши компоненты, вам нужно будет либо использовать библиотеку Redux , либо context .
Ответ №1:
Если я правильно понял, у вас есть две страницы, главное меню и конструктор уровней, и вы хотите переключить, какая из них отображается, верно? Лучший способ сделать это — использовать библиотеку react-router-dom для создания маршрутов в вашем приложении, подробнее об этом здесь .
Но, если вы действительно хотите использовать для этого простое состояние реакции, вы можете передать функцию setPage()
в качестве реквизита двум другим компонентам и вызвать ее из них. Это тоже должно сработать.
Комментарии:
1. К сожалению, если я не ошибаюсь, react router изменяет URL-адрес, и я пытаюсь запустить код под тем же доменным именем. Что касается передачи setPage в качестве реквизита, не могли бы вы случайно привести пример?
2. Вы должны передать
setPage
в качестве аргумента функциональным компонентам, таким как thislevelBuilder(setPage)
иmainMenu(setPage)
. Затем внутри компонентов вы должны вызвать его внутриonClick
. В этом случае вам нужно будет поместитьtoMainMenu()
иtoLevelBuilder()
внутри каждого соответствующего компонента или просто вызватьsetPage("levels")
напрямуюonClick()
.
Ответ №2:
Использование функциональных компонентов. Я написал это дома в текстовом файле, поэтому он может не скомпилироваться, однако, если вы хотите вызвать свои родительские функции из дочерних функциональных компонентов, это один из способов сделать это.
app.js
import React, {useState} from "react";
import StartMenu from "./StartMenu";
import LevelBuilder from "./LevelBuilder";
function App(){
const [currentPage, setPage] = useState("start")
function toMainMenu(){
setPage(prevPage => "main")
}
function toLevelBuilder(){
setPage(prevPage => "levels")
}
let jsx_element = null;
switch(currentPage){
case 'levels':
jsx_element = <LevelBuilder/>;
break;
default:
jsx_element = <StartMenu toMainMenu={toMainMenu} toLevelBuilder={toLevelBuilder}/>;
}
return (
<div>
<span>{currentPage}</span>
{jsx_element}
</div>
)
}
export default App;
StartMenu.js
import React from "react";
function StartMenu(props) {
return(
<div className="container">
<img id = "scan_logo"src={process.env.PUBLIC_URL '/scanlogo.png'} />
<button id="menuStart" onClick={props.toMainMenu}> START </button>
<button id="menuLevel" onClick={props.toLevelBuilder}> LEVEL BUILDER </button>
</div>
)
}
export default StartMenu;
Комментарии:
1. спасибо за помощь, но, похоже, StartMenu по-прежнему не имеет доступа к App.js . С вашими изменениями я в настоящее время получаю сообщение об ошибке «TypeError: не удается прочитать свойство ‘toMainMenu’ из undefined», которое, я полагаю, связано с тем, что startMenu.js не знает, где найти toMainMenu()
2. В коде Null есть пара небольших ошибок, но они не приведут к возникновению возникшей у вас ошибки. Ваша ошибка говорит, что
props
это не определено в StartMenu.js , которым он не является. Вот код и поле его работы: codesandbox.io/s/priceless-lehmann-8lgoc?file=/src/App.js
Ответ №3:
Сначала несколько небольших указателей:
- имена ваших компонентов (
startMenu
,levelBuilder
) должны использовать регистр Pascal - обычной практикой является совпадение имен переменной состояния и «заданных» функций, т. е.
currentPage
иsetCurrentPage
Вероятно, лучшим способом для вас было бы перейти setCurrentPage
в <StartMenu />
from <App />
. Затем, <StartMenu />
когда пользователь нажимает на кнопку, которую вы можете вызвать setCurrentPage('...')
.
Еще одна вещь, которую вы могли бы сделать (но для вас это излишне), — это изучить useContext
.