I am fairly new to React. Currently I have two React components - Article.js and ControlForm.js
My render return in Article.js is this:
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>
);
The ControlForm.js has several form elements (all of which I'd like to be able to pass along if need be), but this is the main one:
<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>
I'd like to be able to set a class on one of the divs in the Article.js based on changing a value in the ControlForm.js
What is the most "React" way to do this? Would creating a common parent to both be the best method (right now, their only parent in common is the main App.js)
Sorry if I don't totally understand how this is supposed to work - this is my first React app.
The class associated with the components are ControlForm and withFetching respectively.
EDIT - the demo example below works, but I have some additional issues with how to integrate it properly into my existing code. Here's the existing functions of 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 });
}
Articles looks like this:
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);
Sorry about all of these questions, I know a lot of this is due to unfamiliarity with React - this is the first thing I've tried to build in React