将状态传递给其他组件的最“反应”方式

时间:2018-09-28 19:53:15

标签: javascript reactjs

我对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中构建的第一件事

3 个答案:

答案 0 :(得分:1)

您想把父母换成他的孩子。

首先,您必须在Article.js中创建一个处理函数,并将其作为属性传递给ControlForm.js。 SELECT categories_id FROM categories WHERE `parent_id` = 151;

然后,您将重点放在ControlForm.js上,只要您想发生,就只需执行作为prop changeDiv传递的函数即可,例如<ControlForm changeDiv={this.changeDiv} />

另请参阅重复的内容:How to update parent's state in React?

答案 1 :(得分:0)

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>
    );
  }
}

答案 2 :(得分:0)

您可以根据状态有条件地呈现一个类,并且您的处理程序缺少onChange事件上的值

这是基于状态动态更改样式的演示 demo