[英]Cleaner way to pass state variables and methods to child components in React?
[英]The most “react” way to pass state to other components
我對React很陌生。 目前我有兩個React組件-Article.js和ControlForm.js
我在Article.js中的渲染返回是這樣的:
return (
<div className="article">
{article_wrapper.map( article =>
<div key={article.node.nid} className="article-main-display">
<h1 className="title" dangerouslySetInnerHTML={createMarkup(article.node.title)}/>
<div className="img-div"><img src={article.node.field_image.src} /></div>
<ControlForm />
<div dangerouslySetInnerHTML={createMarkup(article.node.field_user_hsk_level)} />;
<div className="field-name-field-chinese">
<div dangerouslySetInnerHTML={createMarkup(article.node.chinese)} />;
</div>
</div>
)}
</div>
);
ControlForm.js具有多個表單元素(如果需要,我希望能夠將其全部傳遞),但這是主要的元素:
<div className="form-item form-type-select form-group">
<label className="control-label">Font Size</label>
<select
value={this.state.value}
onChange={this.handleSizeSelect}
id="font-size"
className="form-control form-select"
>
<option value="0">Small</option>
<option value="1">Normal</option>
<option value="2">Large</option>
<option value="3">XL</option>
</select>
</div>
我希望能夠基於更改ControlForm.js中的值在Article.js中的一個div上設置一個類。
最“反應”的方式是什么? 最好同時創建一個共同的父母(目前,他們唯一的共同父母是主要的App.js)。
抱歉,如果我不完全了解它應該如何工作,這是我的第一個React應用程序。
與組件關聯的類分別是ControlForm和withFetching。
編輯-下面的演示示例可以工作,但是在如何將其正確集成到現有代碼中時,我還有一些其他問題。 這是ControlForm的現有功能:
class ControlForm extends Component {
constructor() {
super();
this.state = { toggleActive: false, sizeSelect: "0", speed: 1.3, volume: .6};
this.onToggle = this.onToggle.bind(this);
this.handleSpeedChange = this.handleSpeedChange.bind(this);
this.handleVolumeChange = this.handleVolumeChange.bind(this);
this.handleSizeSelect = this.handleSizeSelect.bind(this);
}
onToggle() {
this.setState({ toggleActive: !this.state.toggleActive });
}
handleSizeSelect(event) {
this.setState({ sizeSelect: event.target.value });
this.setState({font: 'large-font'});
parentMethod(event.target.value);
}
handlePlayClick(e) {
e.preventDefault();
voice.playButtonClick();
}
handlePauseClick(e) {
e.preventDefault();
voice.pauseButtonClick();
}
handleStopClick(e) {
e.preventDefault();
voice.stopButtonClick();
}
handleVolumeChange(event) {
console.log(event.target.value);
this.setState({ volume: event.target.value });
}
handleSpeedChange(event) {
console.log(event.target.value);
this.setState({ speed: event.target.value });
}
文章如下所示:
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
error: null,
dynamicClassName: "parentClass"
};
this.changeClassName = this.changeClassName.bind(this);
}
changeClassName(childData) {
this.setState({
dynamicClassName: childData
});
}
componentDidMount() {
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
//return "test";
return <Comp { ...this.props } { ...this.state } />
}
}
function createMarkup(html) {
return {__html: html};
}
function changeClassName(childData) {
console.log("GETS HERE!")
this.setState({
dynamicClassName: childData
});
}
const Articles = ({ data, isLoading, error }) => {
console.log(data);
console.log(isLoading);
const article_wrapper = data.nodes || [];
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="article">
{article_wrapper.map( article =>
<div key={article.node.nid} className="article-main-display">
<h1 className="title" dangerouslySetInnerHTML={createMarkup(article.node.title)}/>
<div className="img-div"><img src={article.node.field_image.src} /></div>
<ControlForm parentMethod={changeClassName} />
<div dangerouslySetInnerHTML={createMarkup(article.node.field_user_hsk_level)} />;
<div className="field-name-field-chinese">
<div dangerouslySetInnerHTML={createMarkup(article.node.chinese)} />;
</div>
</div>
)}
</div>
);
}
export default withFetching(API)(Articles);
抱歉,所有這些問題,我知道很多原因是由於不熟悉React-這是我嘗試在React中構建的第一件事
你想改變父母從他的孩子。
首先,您必須在Article.js中創建一個處理函數,並將其作為屬性傳遞給ControlForm.js。 <ControlForm changeDiv={this.changeDiv} />
然后,您將重點放在ControlForm.js上,只要您想發生,就只需執行作為prop changeDiv傳遞的函數,例如this.props.changeDiv()
另請參見可能的重復項: 如何在React中更新父級的狀態?
Article.js,
class Article extends React.Component { constructor(props) { super(props); this.state = { dynamicClassName: "parentClass" } this.changeClassName = this.changeClassName.bind(this); } changeClassName(childData) { this.setState({ dynamicClassName: childData }); } // user dynamicClassName wherever u want . return ( < div className = "article" > { article_wrapper.map(article => < div key = { article.node.nid } className = "article-main-display" > < h1 className = "title" dangerouslySetInnerHTML = { createMarkup(article.node.title) } /> < div className = "img-div" > < img src = { article.node.field_image.src } /></div > < ControlForm parentMethod={this.changeClassName} / > < div dangerouslySetInnerHTML = { createMarkup(article.node.field_user_hsk_level) } />; < div className = "field-name-field-chinese" > < div dangerouslySetInnerHTML = { createMarkup(article.node.chinese) } />; < / div > < /div> ) } < /div> ); }
在ControlForm js中,
class ControlForm extends React.Component { constructor(props) { super(props); this.state = { } this.handleSizeSelect= this.handleSizeSelect.bind(this); } handleSizeSelect() { this.props.parentMethod(this.state.value); } render() { return ( <div className="form-item form-type-select form-group"> <label className="control-label">Font Size</label> <select value={this.state.value} onChange={this.handleSizeSelect} id="font-size" className="form-control form-select" > <option value="0">Small</option> <option value="1">Normal</option> <option value="2">Large</option> <option value="3">XL</option> </select> </div> ); } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.