我有一个很大的组件<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>
答案 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;