Обновление значения состояния для файловых функций в React.js

#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 в качестве аргумента функциональным компонентам, таким как this levelBuilder(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 .