![](/img/trans.png)
[英]Accessing a react state created in one component from another component
[英]Accessing state from another component in react
只是學習React並遇到問題。 我有一個選擇器,可以選擇車輛的年份/品牌/型號。 但是,我希望它在更改年份時重置品牌和型號,或者在更改品牌時僅重置型號,以便將這些選項狀態重新設置為null,從而取消選中ui。
但是,問題是我不知道如何使其他人可以使用組件的狀態。 我認為解決方案可能像使用year的onChange函數一樣簡單,然后它將獲取make / model的狀態並重置為null,盡管沒有year.js無法知道其他2個狀態,這是不可能的...
希望你理解我在說什么。 這是代碼。 Year.js
import React, { Component } from 'react';
import '../CSS/App.css';
const vehicleYear = [
{id:1,label:"2019",href:"#"},
{id:2,label:"2018",href:"#"},
{id:3,label:"2017",href:"#"},
{id:4,label:"2016",href:"#"},
{id:5,label:"2015",href:"#"},
{id:6,label:"2014",href:"#"}
];
class Year extends Component {
constructor(props){
super(props);
this.state = {
year: null,
}
}
createYearList = () => {
let listItems = [];
for (let i = 0; i < vehicleYear.length; i++) {
listItems.push(
<li className={`list ${this.state.year === vehicleYear[i].id ? "active" : ""}`} onClick={(e) => {
this.yearClick(e, vehicleYear[i].id, vehicleYear[i].label)
}}>
<a href={vehicleYear[i].href}>{vehicleYear[i].label}</a>
</li>
);
}
return listItems;
};
yearClick = (e, id, label) => {
let state = this.state;
state.year = id;
this.setState(state);
console.log(this.state);
console.log(this.props.year);
};
render() {
return (
<div>
{this.createYearList()}
</div>
)
}
}
export default Year;
Make.js
import React, { Component } from 'react';
import '../CSS/App.css';
const vehicleMake = [
{id:1,label:"POLARIS",href:"#"},
{id:2,label:"CAN_AM",href:"#"},
{id:3,label:"YAMAHA",href:"#"},
{id:4,label:"SUZUKI",href:"#"},
{id:5,label:"ARCTIC-CAT",href:"#"}
];
class Make extends Component {
constructor(props){
super(props);
this.state = {
make: null
}
}
createMakeList = () => {
let listItems = [];
for(let i = 0; i < vehicleMake.length; i++){
listItems.push(
<li className={`list ${this.state.make === vehicleMake[i].id ? "active" : ""}`} onClick={(e)=>{this.makeClick(e, vehicleMake[i].id, vehicleMake[i].label)}}>
<a href={vehicleMake[i].href}>{vehicleMake[i].label}</a>
</li>
);
}
return listItems;
};
makeClick = (e, id, label) => {
console.log(id, label);
let state = this.state;
state.make = id;
this.setState(state);
console.log(state.make);
};
render() {
return (
<div>
{this.createMakeList()}
</div>
)
}
}
export default Make;
Model.js
import React, { Component } from 'react';
import '../CSS/App.css';
const vehicleModel = [
{id:1,label:"RZR 570",href:"#"},
{id:2,label:"RZR 900",href:"#"},
{id:3,label:"RZR S 900",href:"#"},
{id:4,label:"RZR S 1000",href:"#"},
{id:5,label:"RZR S 1000 TURBO",href:"#"}
];
class Model extends Component {
constructor(props){
super(props);
this.state = {
model: null
}
}
createModelList = () => {
let listItems = [];
for(let i = 0; i < vehicleModel.length; i++){
listItems.push(
<li className={`list ${this.state.model === vehicleModel[i].id ? "active" : ""}`} onClick={(e)=>{this.modelClick(e, vehicleModel[i].id, vehicleModel[i].label)}}>
<a href={vehicleModel[i].href}>{vehicleModel[i].label}</a>
</li>
);
}
return listItems;
};
modelClick = (e, id, label) => {
console.log(id, label);
let state = this.state;
state.model = id;
this.setState(state);
};
render() {
return (
<div>
{this.createModelList()}
</div>
)
}
}
export default Model;
這是主要的App.js
import React, { Component } from 'react';
import './CSS/App.css';
import { Container, Row, Col } from 'reactstrap';
import rzrPic from './Media/rzr-xp-1000-eps-trails-rocks-media-location-1-xxs.jpg';
import camsoT4S from './Media/camso-atv-t4s.jpg';
import Year from './Components/Year';
import Make from './Components/Make';
import Model from './Components/Model';
class App extends Component {
render() {
return (
<div className="App">
<Container fluid="true">
<Row>
<Col xs="3" className="categories">
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE YEAR
</h2>
</span>
<div className="categoryList">
<ul>
<Year/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MAKE
</h2>
</span>
<div className="categoryList">
<ul>
<Make/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MODEL
</h2>
</span>
<div className="categoryList">
<ul>
<Model/>
</ul>
</div>
</div>
</Col>
<Col xs="6" className="fill">
<img src={rzrPic} alt="rzr xp 1000"/>
</Col>
<Col xs="3" className="categories">
<span className="categoryHeader2">
<h2 className="categoryHeading">
AVAILABLE TRACKS
</h2>
</span>
<div className="Track">
<img src={camsoT4S} alt="Camso T4S Tracks"/>
<div className="TrackInfo">
<h3>CAMSO T4S - 4 SEASON</h3>
<p>Starting at $3,999.00</p>
<span>
ADD TO CART
</span>
</div>
</div>
<div className="Track">
<div className="TrackInfo">
<h3>CAMSO T4S - 4 SEASON</h3>
<p>Starting at $3,999.00</p>
<p className="select">SELECT</p>
</div>
</div>
</Col>
</Row>
</Container>
</div>
);
}
}
export default App;
在此先感謝您的幫助!
與其將所選的年份/品牌/型號存儲在每個組件中,不如將它們存儲在父App
。 然后,您將在App
組件中處理重置邏輯。
這是重構代碼的方法:
import React, { Component } from "react";
import "../CSS/App.css";
// The list of years is now passed as props
//
// const vehicleYear = [];
class Year extends Component {
// You dont need the constructor anymore as the component
// doesn't have a state to initialize
//
// constructor(props) {}
createYearList = () => {
// Use the year list passed as a prop from the parent
const { vehicleYear } = this.props;
let listItems = [];
for (let i = 0; i < vehicleYear.length; i++) {
listItems.push(
<li
className={`list ${
this.state.year === vehicleYear[i].id ? "active" : ""
}`}
onClick={e => {
this.yearClick(e, vehicleYear[i].id, vehicleYear[i].label);
}}
>
<a href={vehicleYear[i].href}>{vehicleYear[i].label}</a>
</li>
);
}
return listItems;
};
yearClick = (e, id, label) => {
// Call the onClick function passed as a prop from the parent
this.props.onClick(e, id, label);
};
render() {
return <div>{this.createYearList()}</div>;
}
}
export default Year;
我只修改了Year
組件,因為Make
和Model
組件具有相同的結構。 我稍后再講。
這是在App
使用Year
的方法:
import React, { Component } from 'react';
// import ...
// Define the list of years
const vehicleYear = [
{id:1,label:"2019",href:"#"},
{id:2,label:"2018",href:"#"},
{id:3,label:"2017",href:"#"},
{id:4,label:"2016",href:"#"},
{id:5,label:"2015",href:"#"},
{id:6,label:"2014",href:"#"}
];
class App extends Component {
constructor(props){
super(props);
// Initialise the state of the App component
this.state = {
year: null,
}
}
// Move the click handler from the Year component to its parent component
yearClick = (e, id, label) => {
this.setState({
year: id
});
};
render() {
return (
<div className="App">
<Container fluid="true">
<Row>
<Col xs="3" className="categories">
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE YEAR
</h2>
</span>
<div className="categoryList">
<ul>
{/* Pass the list of years, the selected year and the handler to
select a year to the Year component */}
<Year vehicleYear={vehicleYear} selectedYear={this.state.year} onClick={this.yearClick} />
</ul>
</div>
</div>
...
</Row>
</Container>
</div>
);
}
}
export default App;
現在,您可以完全控制Year
並由App
組件處理邏輯。 如果要重置選定的年份,只需在App
組件中創建並調用這樣的函數:
resetYear = () => {
this.setState({
year: null
});
};
您可以將Year
, Make
和Model
組件重新引用為一個可重用組件,因為它們的結構完全相同。 這是ListComponent
提取的ListComponent
:
// The list components takes three arguments:
// - itemsList: items to be displayed
// - selectedItemId: the id of the selected item
// - onSelect: a function to call when an item is selected
class ListComponent extends Component {
render() {
const { itemsList, selectedItemId, onSelect } = this.props;
return (
<div>
{itemsList.map(item => (
<li
className={`list ${selectedItemId === item.id ? "active" : ""}`}
onClick={e => {
onSelect(e, item.id, item.label);
}}
>
<a href={item.href}>{item.label}</a>
</li>
))}
</div>
);
}
}
export default ListComponent;
您可以像這樣使用它:
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE YEAR
</h2>
</span>
<div className="categoryList">
<ul>
<ListComponent onSelect={this.selectYear} itemsList={vehicleYear} selectedItemId={this.state.year}/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MAKE
</h2>
</span>
<div className="categoryList">
<ul>
<ListComponent onSelect={this.selectMake} itemsList={vehicleMake} selectedItemId={this.state.make}/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MODEL
</h2>
</span>
<div className="categoryList">
<ul>
<ListComponent onSelect={this.selectModel} itemsList={vehicleModel} selectedItemId={this.state.model}/>
</ul>
</div>
</div>
最簡單的解決方案是在這種情況下將您的狀態保留在父級中,或者在組件中臨時創建一個組件作為父級,然后簡單地傳遞一個onChangeYear屬性,例如更改父級的狀態。
import React, { Component } from 'react';
import './CSS/App.css';
import { Container, Row, Col } from 'reactstrap';
import rzrPic from './Media/rzr-xp-1000-eps-trails-rocks-media-location-1-xxs.jpg';
import camsoT4S from './Media/camso-atv-t4s.jpg';
import Year from './Components/Year';
import Make from './Components/Make';
import Model from './Components/Model';
class App extends Component {
contructor(props) {
super(props);
this.state = { year: "" }
}
render() {
return (
<div className="App">
<Container fluid="true">
<Row>
<Col xs="3" className="categories">
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE YEAR
</h2>
</span>
<div className="categoryList">
<ul>
<Year onChangeYear={(year) => {this.setState({year})/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MAKE
</h2>
</span>
<div className="categoryList">
<ul>
<Make/>
</ul>
</div>
</div>
<div>
<span className="categoryHeader">
<h2 className="categoryHeading">
VEHICLE MODEL
</h2>
</span>
<div className="categoryList">
<ul>
<Model/>
</ul>
</div>
</div>
</Col>
<Col xs="6" className="fill">
<img src={rzrPic} alt="rzr xp 1000"/>
</Col>
<Col xs="3" className="categories">
<span className="categoryHeader2">
<h2 className="categoryHeading">
AVAILABLE TRACKS
</h2>
</span>
<div className="Track">
<img src={camsoT4S} alt="Camso T4S Tracks"/>
<div className="TrackInfo">
<h3>CAMSO T4S - 4 SEASON</h3>
<p>Starting at $3,999.00</p>
<span>
ADD TO CART
</span>
</div>
</div>
<div className="Track">
<div className="TrackInfo">
<h3>CAMSO T4S - 4 SEASON</h3>
<p>Starting at $3,999.00</p>
<p className="select">SELECT</p>
</div>
</div>
</Col>
</Row>
</Container>
</div>
);
}
}
export default App;
如果您發現自己的Web應用程序中有很多組件,我會考慮集成Redux以全局處理狀態https://redux.js.org/introduction/getting-started 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.