React:在页面,NavBar和模态组件之间传递状态

时间:2020-05-18 05:04:42

标签: javascript reactjs react-router-dom react-bootstrap

我仍在尝试摆脱React中组件之间传递状态的困扰。我有一个NavigationBarRunSimsModal组件,以及一个Ratings页面。

用户在Ratings页面上调整输入,然后该页面包含进入RunSimsModal的输入。我不确定如何执行此操作,因为只能从RunSimsModal访问NavigationBarNavigationBar随时都不知道Ratings的状态。如何将数据/状态从Ratings传递到RunSimsModal

NavigationBar.js

import React, {useState} from "react";
import { Nav, Navbar, Form, FormControl, Button } from "react-bootstrap";
import styled from "styled-components";
import RunSimsModal from "./RunSimsModal";

const Styles = styled.div`
  .navbar {
    background-color: #222;
  }
  a,
  .navbar-nav,
  .navbar-light .nav-link {
    color: #9fffcb;
    &:hover {
      color: white;
    }
  }
  .navbar-brand {
    font-size: 1.4em;
    color: #9fffcb;
    &:hover {
      color: white;
    }
  }
  .form-center {
    position: absolute !important;
    left: 55%;
    right: 25%;
  }
`;

export const NavigationBar = function () {
  const [modalShow, setModalShow] = useState(false);
  return <Styles>
    <Navbar expand="lg" fixed ="top">
      <Navbar.Brand href="/">Decade3</Navbar.Brand>
      <Navbar.Toggle aria-controls="basic-navbar-nav" />
      <Form className="form-center">
        <FormControl type="text" placeholder="Search" className="" />
      </Form>
      <Navbar.Collapse id="basic-navbar-nav">
        <Nav className="ml-auto">
          <Button variant="primary" onClick={() => setModalShow(true)} >Run Sims</Button>{' '}
          <Nav.Item>
            <Nav.Link href="/">Home</Nav.Link>
          </Nav.Item>
          <Nav.Item>
            <Nav.Link href="/about">About</Nav.Link>
          </Nav.Item>
        </Nav>
      </Navbar.Collapse>
    </Navbar>

    <RunSimsModal show={modalShow} onHide={() => setModalShow(false)} />
  </Styles>
}

RunSimsModal.js

import React, { useState} from "react";
import { Button, Modal, FormFile, Form } from "react-bootstrap";
import * as outrightSimulatorApi from "../api/outrightSimulatorApi";
import Body from "../api/model/body.json";
import { withRouter } from "react-router-dom";

function RunSimsModal({ staticContext, ...props }) {
  const [numberofSims, setNumberOfSims] = useState("");
  const [simName, setSimName] = useState("");

  const runSims = event => {
    console.log("triggered");
    outrightSimulatorApi.runSim(
      Body.clientId,
      simName,
      numberofSims,
      Body.teamRatings, //This is the data I want to pass in from the Ratings page, it's an array
      Body.fixtureOverrides,
      Body.tournamentId
    );
    props.history.push("/reports");
  };

  return (
    <Modal
      {...props}
      size="lg"
      aria-labelledby="contained-modal-title-vcenter"
      centered
    >
      <Modal.Header closeButton>
        <Modal.Title id="contained-modal-title-vcenter">
          Run Simulations
        </Modal.Title>
      </Modal.Header>

      <Modal.Body>
        <h4>Run Sims</h4>

        <Form onSubmit={runSims}>
          <Form.Group controlId="formBasicEmail">
            <Form.Label>Number Of Simulations</Form.Label>
            <Form.Control
              required
              type="text"
              placeholder="Enter number of sims"
              value={numberofSims}
              onChange={e => setNumberOfSims(e.target.value)}
            />
          </Form.Group>

          <Form.Group controlId="formBasicEmail">
            <Form.Label>Simulation Name</Form.Label>
            <Form.Control
              required
              type="text"
              placeholder="Enter simulation name"
              value={simName}
              onChange={e => setSimName(e.target.value)}
            />
          </Form.Group>

          <Form.Group controlId="formBasicEmail">
            <Form.Label>Tournament Type</Form.Label>
            <Form.Control as="select">
              <option>LEAGUE</option>
            </Form.Control>
          </Form.Group>

          <Form.Group controlId="formBasicEmail">
            <Form.Label>Teams in tournament</Form.Label>
            <FormFile.Input />
          </Form.Group>

          <Button type="submit">Run</Button>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button onClick={props.onHide}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
}

export default withRouter(RunSimsModal);

Ratings.js

import React, { useState, useEffect } from "react";
import styled from "styled-components";
import { Table } from "react-bootstrap";
import NumericInput from "react-numeric-input";
import Teams from "../assets/Teams.js";
import { loadRatings } from "../actions/outrightSimulatorActions";
import ratingsStore from "../stores/ratingsStore";

const GridWrapper = styled.div`
  display: grid;
  grid-gap: 10px;
  margin-top: 4.5em;
  margin-left: 6em;
  margin-right: 6em;
  grid-template-columns: repeat(1, 1fr);
  grid-auto-rows: minmax(25px, auto);
`;

const TeamIcon = styled.span`
  margin-right: 0.5em;
`;

const teams = Teams;

function Display() {
  return (
    <GridWrapper>
      <div>
        <RatingsGrid />
      </div>
    </GridWrapper>
  );
}

function RatingsGrid() {
  const [ratings, setRatings] = useState(ratingsStore.getRatings());

  useEffect(() => {
    ratingsStore.addChangeListener(onChange);

    if (ratingsStore.getRatings().length === 0) loadRatings();

    return () => {
      ratingsStore.removeChangeListener(onChange);
    };
  }, []);

  function onChange() {
    console.log("ratings changed");
    setRatings(ratingsStore.getRatings());
  }

  return (
    <Table striped bordered hover size="sm">
      <thead>
        <tr>
          <th>Teams</th>
          <th>Ratings</th>
          <th>Home Advantage</th>
        </tr>
      </thead>
      <tbody>
        {ratings.map(rating => (
          <tr key={rating.teamId}>
            <td>
              <TeamIcon>
                <span>
                  <img
                    src={teams.find(t => t.id === rating.teamId).icon}
                    className="icon"
                    height="42"
                    width="42"
                    alt={rating.teamName}
                  />
                </span>
                {rating.teamName}
              </TeamIcon>
            </td>
            <td>
              <NumericInput
                value={rating.rating}
                step={0.01}
                mobile={false}
                size="14"
              />
            </td>
            <td>
              <NumericInput value={0.4} step={0.01} mobile={false} size="14" />
            </td>
          </tr>
        ))}
      </tbody>
    </Table>
  );
}

export default Display;

0 个答案:

没有答案