我有4个嵌套组件,<CompD>
嵌套在<CompC>
内,而<CompB>
嵌套在<CompA>
内。
<CompD>
包含一个带有onSubmit={onSubmit}
的Redux表单和一堆输入,以及一个带有type="submit"
的Save按钮
当前带有按钮的<CompD>
片段:
const propTypes = {
firstName: PropTypes.string,
secondName: PropTypes.string
};
const defaultTypes = {
firstName = " ",
secondName = " "
};
const PollForm = ({
firstName,
secondName
}) => (
<Form onSubmit={onSubmit}>
.
.
<button type="submit">
'Save'
</button>
</Form>
);
PollForm.propTypes = propTypes;
PollForm.defaultProps = defaultProps;
export default PollForm;
我想将按钮移至<CompA>
,所以<CompA>
中的按钮的行为与<CompD>
中的按钮完全相同,并提交表单。
添加了新按钮的<CompA>
片段:
const propTypes = {
onSubmit: PropTypes.func, ...
};
const defaultTypes = {
onSubmit: () = {}, ...
};
class Config extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this); ...
}
handleSubmit(data) {
this.props.onSubmit(data);
}
render() {
const {
} = this.props;
return (
.
.
<button onClick={onSubmit}>
'Save'
</button>
)
}
}
如何在handleSubmit(data)
中传递<CompA
函数中来自表单的数据
有什么想法可以做到吗?
答案 0 :(得分:1)
反应组件使用道具相互通信。 Parent -> Child
经过props
,Child -> Parent
经过callback props
。另一种方法是使用新的Context API
。如果您有一个非常深的嵌套结构,那会更好。
下一个我展示了如何通过道具来完成。
class CompB extends React.Component {
state = {
name: "John Doe",
email: "john@doe.com"
}
handleChange = e => {
const {name, value} = e.target;
this.setState({[name]: value})
}
handleSubmit = e => {
e.preventDefault();
this.submit(this.state)
}
submit = (data) => {
console.log("submitted", data, +new Date());
this.props.onSubmit(data);
}
componentDidUpdate (oldProps) {
if (!oldProps.shouldSubmit && this.props.shouldSubmit){
this.submit(this.state);
}
}
render () {
const { name, email } = this.state;
return (
<form onChange={this.handleChange} onSubmit={this.handleSubmit}>
<div>
<label>
Name
<input name="name" type="text" value={name} />
</label>
</div>
<div>
<label>
Email
<input name="email" type="email" value={email} />
</label>
</div>
</form>
)
}
}
class CompA extends React.Component {
state = {
shouldSubmit: false,
}
submit = () => {
this.setState({shouldSubmit: true})
}
handleSubmit = () => {
this.setState({shouldSubmit: false})
}
render () {
const {shouldSubmit} = this.state;
return (
<div>
<CompB
shouldSubmit={shouldSubmit}
onSubmit={this.handleSubmit}
/>
<button
type="button"
onClick={this.submit}
>
Submit
</button>
</div>
)
}
}
ReactDOM.render(<CompA />, document.querySelector("#root"))
<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>
答案 1 :(得分:1)
您可以将表单提交状态和逻辑从<CompD>
提升到<CompA>
,并且可以使用React Context提供深入到<CompD>
的表单状态和处理程序,像这样:
import React from 'react';
import ReactDOM from 'react-dom';
const FormContext = React.createContext();
function CompB({ children }) {
return <div id="B">{children}</div>;
}
function CompC({ children }) {
return <div id="C">{children}</div>;
}
function CompD() {
return (
<FormContext.Consumer>
{({ onSubmit, onChange, name }) => {
return (
<form onSubmit={onSubmit}>
<label>
Name:
<input type="text" value={name} onChange={onChange} />
</label>
<input type="submit" value="submit-input" />
</form>
);
}}
</FormContext.Consumer>
);
}
class CompA extends React.Component {
onChange = ({ target: { value } }) => {
this.setState({ name: value });
};
onSubmit = event => {
event.preventDefault();
console.log('Submitting name: ', this.state.name);
};
state = {
name: 'defaultName',
onSubmit: this.onSubmit,
onChange: this.onChange,
};
render() {
return (
<FormContext.Provider value={this.state}>
<CompB>
<CompC>
<CompD />
</CompC>
</CompB>
<button name="submit" onClick={this.onSubmit}>submit-btn<button/>
</FormContext.Provider>
);
}
}
ReactDOM.render(
<CompA />,
document.getElementById('root'),
);
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
但是将表单与“提交”按钮分开看起来确实很冗长。不知道为什么会有这样的需求,但是通常最好将它们组合在一个组件中。