我仍在尝试摆脱React中组件之间传递状态的困扰。我有一个NavigationBar
和RunSimsModal
组件,以及一个Ratings
页面。
用户在Ratings
页面上调整输入,然后该页面包含进入RunSimsModal
的输入。我不确定如何执行此操作,因为只能从RunSimsModal
访问NavigationBar
。 NavigationBar
随时都不知道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;