单击reactjs中的按钮将组件附加到另一个组件

时间:2018-07-18 14:15:28

标签: javascript reactjs

我有一个很大的组件<User />和一个很小的<Task />,想给一个大组件一个按钮,然后单击它,将组件<Task />附加到。

User.jsx

<div>
  <Task />
  <button onClick={`Function here to append a new Task component`}>
    New Task
  </button>
</div>

Task.jsx

<div>
  This is New task
</div>

4 个答案:

答案 0 :(得分:6)

您应该让React渲染所有内容,而您的工作只是告诉React要渲染什么,以及您的情况是多少次。为此,可以使用counter来跟踪应在<Example>组件内“注入”动态添加的数量。

这里需要思想转变,因为在您的示例中,您来自一个认为单击处理程序本身应该修改DOM的地方,而在React中这是一个反模式。

相反,您应该使用 state ,这意味着点击处理程序应更新主机组件的状态,这将触发重新渲染(这是React的工作方式),并且在下一个渲染周期,您添加的组件将被渲染与计数器值一样多的次数,因为该计数器更改是触发重新渲染的原因。

在React中,props和state是触发重新渲染的方式,并且任何DOM修改都应通过更改内部组件的状态或通过从父组件发送不同的props来完成。


在下面的示例中,我使用,而是使用 Hooks ,因为我已经停止使用<一旦钩子被释放,em> class 就会全部消失,因为我认为它更干净:

const {useState, useCallback, Fragment} = React

// The added element component
const AddedElement = () => <div><input placeholder='text box' /></div>

// The parent component
const App = () => {
  const [count, setCount] = useState(0) // Name it however you wish

  return <Fragment>
    <button onClick={() => setCount(count + 1)}>Click me</button>
    { Array(count).fill(<AddedElement />) }
  </Fragment>
}

// Render 
ReactDOM.render(<App />, document.getElementById("react"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>

如果您对如何反复渲染相同的组件感兴趣,我已经在以下问题中对此问题写过答案:How can I render repeating React elements?

答案 1 :(得分:3)

您可以执行以下操作。

const User = () => {
  return <p>User</p>
}

class App extends React.Component {

  state = {
    users: []
  }

  addUser = () => {
    this.setState({
      users: [...this.state.users, <User />]
    })
  }

  render() {
    return (
      <div>
        <button onClick={this.addUser}>Add User</button>
        {this.state.users}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

有一个代码沙箱here

答案 2 :(得分:0)

const Task = (props) => {
  return (
    <li>{props.value}</li>
  )
}

class TaskForm extends React.Component {
  state = { 
    value : ''
  };
  
  handleChange = (e) => {
    const { value } = e.target;
    this.setState(_ => ({
      value
    }));
  }
  
  handleAdd = (e) => {
    const { value } = this.state;
    if (value === '') { return; }
    this.props.onNewTask(value);
    this.setState(_ => ({
      value : ''
    }))
  }
  
  render () {
    const { value } = this.state;
    return (
      <div>
        <input 
          value={value} 
          onChange={this.handleChange}
        />
        <button onClick={this.handleAdd}>Add</button>
      </div>
    )
  }
}

class User extends React.Component {
  state = {
    tasks : []
  }
  
  handleNewTask = (task) => {
    this.setState(state => ({
      ...state,
      tasks : [
        ...state.tasks,
        task
      ]
    }))
  }
  
  renderTasks () {
    const tasks = this.state.tasks.map(t => (
            <Task key={t} value={t} />
    ));
    return (
      <ul>
        {tasks}
      </ul>
    )
  }
  
  render () {
    return (
      <div>
        <TaskForm onNewTask={this.handleNewTask}/>
        {this.renderTasks()}
      </div>
    )
  }
}


ReactDOM.render(<User/>, document.querySelector('#app'));
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.production.min.js"></script>
</head>
<body>
 <div id="app"></div>
</body>
</html>

答案 3 :(得分:0)

import React from "react";
import "./styles.css";

const Element = () => {
  return (
    <div style={{ marginTop: "10px" }}>
      <input type="file" />
      <select id="cars" name="carlist" form="carform">
        <option value="volvo">Volvo</option>
        <option value="saab">Saab</option>
        <option value="opel">Opel</option>
        <option value="audi">Audi</option>
      </select>
    </div>
  );
};

class App extends React.Component {
  state = {
    elements: [
      <div style={{ marginTop: "10px" }}>
        <input type="file" />
        <select id="cars" name="carlist" form="carform">
          <option value="volvo">Volvo</option>
          <option value="saab">Saab</option>
          <option value="opel">Opel</option>
          <option value="audi">Audi</option>
        </select>
      </div>
    ]
  };

  addUser = () => {
    this.setState({
      elements: [...this.state.elements, <Element />]
    });
  };

  render() {
    return (
      <div className="App">
        <h3>Append a React component in another on button click</h3>
        {this.state.elements}

        <button onClick={this.addUser} style={{ marginTop: "10px" }}>
          Add User
        </button>
      </div>
    );
  }
}

export default App;