与Pass props to parent component in React.js类似,但我只想将子组件的默认道具放入父级。
那我为什么要这么做?
好吧,我有一个父组件,它呈现包含HTML表单的子组件。父进程的render()方法将其状态数据作为props传递给子进程。
最初,子表单应仅包含一些默认数据。从子组件中定义的defaultProp获取数据是有意义的。毕竟,我不想在父级状态下设置一组默认数据,仅用于将其作为默认道具传递给子级。父母不应该定义孩子的默认道具。孩子应该知道它自己的默认道具是什么。
所以在我的初始父渲染()中,我将状态保留为undefined。当它作为未定义的道具传递给孩子时,孩子将使用其defaultProps。这正是我想要的。
时间流逝......
现在,用户更改子组件表单上的字段。我通过回调函数将该更改传递回父级,以便重新计算父级的新状态。然后我调用父级中的setState()
来正常重新渲染所有子组件。
问题是我需要父亲的状态作为一个对象,包含更多嵌套对象,并使用[React Immutability Helpers] [1]来计算父级中的新状态,如下所示:
handleFormFieldChange(e) {
// reactUpdate imported from 'react-addons-update'
var newState = reactUpdate(this.state, {
formData: {values: {formFieldValues: {[e.currentTarget.name]: {$set: e.currentTarget.value}}}}
});
this.setState(newState);
}
第一次运行此代码时,它会抛出一个错误,因为它正在尝试更新状态值,并且没有要更新的状态。 (我保留未定义,记住!)
如果我试图通过设置一个空对象的默认初始状态(每个都有嵌套的空对象)来解决这个问题,我会遇到一个catch-22。在第一次渲染时,这些空值将作为空道具传递给子项,因此会覆盖我为子组件设置的defaultProp。无赖!
因此,据我所知,我需要一个明智的初始状态传递给子组件,但没有(重新)在父组件中再次定义整个事物。因此,在这种情况下,我认为将子项的defaultProps拉入父项是有意义的,只是为了设置父项的初始状态。
我有办法做到这一点,我稍后会发布。但在我这样做之前,有没有人有更好的方法呢?是否可以避免必须将defaultProps从子项传递给父项?
答案 0 :(得分:2)
如果您正在使用#include <iostream>
void swap( char* f, char* t ){
char temp = *f;
*f = *t;
*t = temp;
}
void permutation(char arr[], int size)
{
--size;
if( size == 0 ){
std::cout << arr << std::endl;
return;
}
for(int i=0; i < size; i++)
{
swap(&arr[size - 1], &arr[i]);
permutation(arr, size);
swap(&arr[size - 1], &arr[i]);
}
}
int main(){
char str[] = "0123";
permutation( str, sizeof(str) );
}
,则React.Component
是该类中的静态对象,因此很容易获得。
defaultProps
父母只需要这样做:
export default class Child extends React.Component {
static defaultProps = { ... }
}
// If you don't have es7 static support you can add it after the class def:
Child.defaultProps = { ... }
访问它。
答案 1 :(得分:1)
As threatened in the original post, here's how I'm getting the child's default props sent up to the parent.
I'm using ES6 Classes and the module pattern, with Webpack and Babel to handle the building and transpiling.
So I have two files, let's call them Parent.jsx and ChildForm.jsx. Here's how ChildForm.jsx might look (NB: not working code!):
class ChildForm extends React.Component {
render() {
var fieldValues= this.props.formData.formFieldValues;
return(
<form>
Field 1: <input type="text"
name="field1"
value={fieldValues.field1}
onChange={this.props.handleFieldChange} />
</form>
);
}
}
export function getDefaultProps() {
return {
formData: {
formFieldValues: {
field1: "Apples",
field2: "Bananas"
}
}
};
}
ChildForm.defaultProps = getDefaultProps();
export default ChildForm;
The trick is to move the setting of defaultProps to a separate function, which is also exported from the ChildForm.jsx. Having done that, you can probably guess what I'm going to do in the Parent.jsx module! Let's take a look:
import reactUpdate from 'react-addons-update';
import ChildForm from "./ChildForm.jsx";
import {getDefaultProps as getChildFormDefaultProps} from "./ChildForm.jsx";
class Parent extends React.Component {
constructor(props) {
super(props);
var formDefaultProps = getChildFormDefaultProps();
this.state = {
formData: formDefaultProps
};
this.handleFormFieldChange.bind(this);
}
handleFormFieldChange(e) {
var newState = reactUpdate(this.state, {
formData: {values: {formFieldValues: {[e.currentTarget.name]: {$set: e.currentTarget.value}}}}
});
this.setState(newState);
}
render() {
return (
<div>
<ChildForm
formData={this.state.formData}
handleFieldChange={this.props.handleFormFieldChange} /}
</div>
);
}
}
I import the getDefaultProps function from the ChildForm.jsx module and then use that to set the default state for ChildForm at the Parent.jsx level. That state is then passed down to ChildForm as props.
Although this works, I can't help feeling that it's rather clunky. Although I'm defining the defaultProps at the ChildForm.jsx level, where they should be, they're never actually used as defaultProps at that level! Rather, they're passed up the Parent, which uses them to set state, which in turn is passed down to ChildForm as real props.
Still, this is preferable to having to define a default state for the ChildForm component all over again in the Parent component. So it will do for now, unless any of you kind people can suggest something cleaner!