React-Redux与Bootstrap——模态组件

React-Redux with Bootstrap -- modal component

本文关键字:模态 组件 Bootstrap React-Redux      更新时间:2023-09-26

我很难在React-Redux中使用Bootstrap的模态来应用组件与容器之间的概念。

本质上,我不想重新创建特定的模态,而是想创建一个包含模态模板的React组件。

为了说明我的例子,这里有一个我想实现的FCC项目:

https://codepen.io/FreeCodeCamp/full/xVXWag/

"添加配方"answers"编辑"具有相同的组件,但当被调用时,它被不同的容器使用(这是正确的心态吗?)

我有以下代码在我的一个容器"添加配方":

import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
import { addRecipe } from '../actions/index';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

class AddRecipeButton extends Component{
  constructor(props){
    super(props);
    this.state = {recipeName: '', userIngredients: '', showModal: false};
    this.close = this.close.bind(this);
    this.open = this.open.bind(this);
    this.onClickSubmit = this.onClickSubmit.bind(this);
    this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
    this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
  }
  close() {
    this.setState({ showModal: false, recipeName: '', userIngredients: '' });
  }
  open() {
    this.setState({ showModal: true });
  }
  onClickSubmit(){
    const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
    this.props.addRecipe([this.state.recipeName, splitIngredients])
    this.setState({ showModal: false, recipeName: '', userIngredients: '' });
  }
  handleRecipeNameChange(event){
    this.setState({recipeName: event.target.value})
  }
  handleUserIngredientsChange(event){
    this.setState({userIngredients: event.target.value})
  }
  render(){
    const centerText = {
      textAlign : 'center'
    }
    return(
      <div>
        <Button
          bsStyle="success"
          onClick={this.open}
          >Add Recipe
        </Button>
        <Modal show={this.state.showModal} onHide={this.close}>
          <Modal.Header closeButton>
            <Modal.Title style={centerText}>Add Recipe</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <form>
              <div className="form-group">
                <label htmlFor="recipeName">Name of Recipe:</label>
                <input
                  value={this.state.recipeName}
                  onChange={this.handleRecipeNameChange}
                  type="text"
                  className="form-control"
                  id="recipeName" />
              </div>
              <div className="form-group">
                <label htmlFor="userIngredients">Ingredients:</label>
                <textarea
                  placeholder="you can seperate by comma"
                  onChange = {this.handleUserIngredientsChange}
                  value={this.state.userIngredients}
                  type="text"
                  className="form-control"
                  id="userIngredients" />
              </div>
            </form>
          </Modal.Body>
          <Modal.Footer>
            <Button
            bsStyle="info"
            onClick={this.onClickSubmit}>Add Recipe
            </Button> <Button
            bsStyle="danger"
            onClick={this.close}>Close
            </Button>
          </Modal.Footer>
        </Modal>
      </div>
    )
  }
}
function mapDispatchToProps(dispatch){
  return bindActionCreators({addRecipe}, dispatch)
}
export default connect(null,mapDispatchToProps)(AddRecipeButton)

虽然这可以工作,但我已经知道渲染函数应该调用一个组件来完成模态的实际渲染。

我想我的问题是如何创建模态组件和保持模态窗口状态的跟踪?

编辑:那些好奇的人,我能够实现它对我有用的东西。

模态组件:

import React, { Component } from 'react'
import { Button, Modal } from 'react-bootstrap';
export default (props) => {
  return (
    <Modal show={props.showModal} onHide={props.toggleModal}>
      <Modal.Header closeButton>
        <Modal.Title>{props.title}</Modal.Title>
      </Modal.Header>
      <Modal.Body>
      <form>
        <div className="form-group">
          <label htmlFor="recipeName">Name of Recipe:</label>
          <input
            value={props.recipeName}
            onChange={props.handleRecipeNameChange}
            type="text"
            className="form-control"
            id="recipeName" />
        </div>
        <div className="form-group">
          <label htmlFor="userIngredients">Ingredients:</label>
          <textarea
            placeholder="you can seperate by comma"
            onChange = {props.handleUserIngredientsChange}
            value={props.userIngredients}
            type="text"
            className="form-control"
            id="userIngredients" />
        </div>
      </form>
      </Modal.Body>
      <Modal.Footer>
        <Button
        bsStyle="info"
        onClick={props.onClickSubmit}>Add Recipe
        </Button> <Button
        bsStyle="danger"
        onClick={props.toggleModal}>Close
        </Button>
      </Modal.Footer>
    </Modal>
  )
}

添加配方按钮容器(智能组件)

import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
import { addRecipe } from '../actions/index';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import MyModal from '../components/mymodal';
class AddRecipeButton extends Component{
  constructor(props){
    super(props);
    this.state = {
      recipeName: '',
      userIngredients: '',
      showModal: false
    };
    this.onClickSubmit = this.onClickSubmit.bind(this);
    this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
    this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
    this.toggleModal = this.toggleModal.bind(this);
  }
  toggleModal(){
    this.setState({
        showModal: !this.state.showModal
    });
  }
  onClickSubmit(){
    const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
    this.props.addRecipe([this.state.recipeName, splitIngredients])
    this.toggleModal()
  }
  handleRecipeNameChange(event){
    this.setState({recipeName: event.target.value})
  }
  handleUserIngredientsChange(event){
    this.setState({userIngredients: event.target.value})
  }
  render(){
    return (
      <div>
        <Button
          bsStyle="success"
          onClick={this.toggleModal}
          >Add Recipe
        </Button>
        <MyModal
          toggleModal={this.toggleModal}
          showModal={this.state.showModal}
          recipeName={this.state.recipeName}
          userIngredients={this.state.userIngredients}
          handleRecipeNameChange={this.handleRecipeNameChange}
          handleUserIngredientsChange={this.handleUserIngredientsChange}
          onClickSubmit={this.onClickSubmit}
        />
      </div>
    )
  }
}
function mapDispatchToProps(dispatch){
  return bindActionCreators({addRecipe}, dispatch)
}
export default connect(null,mapDispatchToProps)(AddRecipeButton)

像这样的东西会工作(有点快速的工作,但你得到的想法…?)

// Create a React component for your modal:
var MyModal = React.createClass({
    render: function() {
        return (
         <Modal onHide={this.props.handleToggle}>
          <Modal.Header closeButton>
            <Modal.Title style={centerText}>Add Recipe</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <form>
              <div className="form-group">
                <label htmlFor="recipeName">Name of Recipe:</label>
                <input
                  value={this.props.recipeName}
                  onChange={this.props.handleRecipeNameChange}
                  type="text"
                  className="form-control"
                  id="recipeName" />
              </div>
              <div className="form-group">
                <label htmlFor="userIngredients">Ingredients:</label>
                <textarea
                  placeholder="you can seperate by comma"
                  onChange = {this.props.handleUserIngredientsChange}
                  value={this.props.userIngredients}
                  type="text"
                  className="form-control"
                  id="userIngredients" />
              </div>
            </form>
          </Modal.Body>
          <Modal.Footer>
            <Button
            bsStyle="info"
            onClick={this.props.onClickSubmit}>Add Recipe
            </Button> <Button
            bsStyle="danger"
            onClick={this.props.handleToggle}>Close
            </Button>
          </Modal.Footer>
        )
    }
});
// Return modal in render function and pass parent components state and functions down through props:
var AddRecipeButton = React.createClass({
  getInitialState: function() {
    return {
        isModalOpen: false,
        recipeName: '',
        userIngredients: ''
    };
  },
  toggleModal: function() {
    this.setState({
        isModalOpen: !this.state.isModalOpen
    });
  },
  onClickSubmit(){
    const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
    this.props.addRecipe([this.state.recipeName, splitIngredients])
    this.toggleModal();
  },
  handleRecipeNameChange(event){
    this.setState({recipeName: event.target.value})
  },
  handleUserIngredientsChange(event){
    this.setState({userIngredients: event.target.value})
  },
  renderModal: function() {
    if (this.state.isModalOpen) {
        return 
        <MyModal
            toggleModal={this.toggleModal}
            onClickSubmit={this.onClickSubmit}
            handleRecipeNameChange={this.handleRecipeNameChange}
            handleUserIngredientsChange={this.handleUserIngredientsChange}
        />;
    }
  },
  render: function() {
    {this.renderModal()}
  }
});