在 React.js 中触发子项重新渲染
Trigger child re-rendering in React.js
父组件(在我的示例中为MyList
)组件通过子组件(MyComponent
)呈现数组。父决定更改数组中的属性,React 触发子重新渲染的方式是什么?
我想出的只是在调整数据后 this.setState({});
在 Parent 中。这是触发更新的 hack 还是 React 方式?
JS Fiddle:
https://jsfiddle.net/69z2wepo/7601/
var items = [
{id: 1, highlighted: false, text: "item1"},
{id: 2, highlighted: true, text: "item2"},
{id: 3, highlighted: false, text: "item3"},
];
var MyComponent = React.createClass({
render: function() {
return <div className={this.props.highlighted ? 'light-it-up' : ''}>{this.props.text}</div>;
}
});
var MyList = React.createClass({
toggleHighlight: function() {
this.props.items.forEach(function(v){
v.highlighted = !v.highlighted;
});
// Children must re-render
// IS THIS CORRECT?
this.setState({});
},
render: function() {
return <div>
<button onClick={this.toggleHighlight}>Toggle highlight</button>
{this.props.items.map(function(item) {
return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>;
})}
</div>;
}
});
React.render(<MyList items={items}/>, document.getElementById('container'));
您应该通过调用 setState()
并提供您想要向下传播的新道具来触发重新渲染。
如果你真的想强制更新你也可以调用 forceUpdate()
.
如果你看一下上面的例子,page, you can see that setState
is the method used to update and trigger a re-rendering. The documentation 也清楚地说明了(啊哈哈!)。
在你的情况下,我会打电话给 forceUpdate
。
编辑:正如 Jordan 在评论中提到的,最好将项目存储为状态的一部分。这样你就不必调用 forceUpdate
但你会真正更新组件的状态,因此具有更新值的常规 setState
会更好。
这里的问题是您将状态存储在 this.props
而不是 this.state
中。由于此组件正在改变 items
,因此 items
是状态并且应该存储在 this.state
中。 (这里是 good article on props vs. state。)这解决了您的渲染问题,因为当您更新 items
时,您将调用 setState
,这将自动触发重新渲染。
下面是你的组件使用 state 而不是 props 的样子:
var MyList = React.createClass({
getInitialState: function() {
return { items: this.props.initialItems };
},
toggleHighlight: function() {
var newItems = this.state.items.map(function (item) {
item.highlighted = !item.highlighted;
return item;
});
this.setState({ items: newItems });
},
render: function() {
return (
<div>
<button onClick={this.toggleHighlight}>Toggle highlight</button>
{ this.state.items.map(function(item) {
return <MyComponent key={item.id} text={item.text}
highlighted={item.highlighted}/>;
}) }
</div>
);
}
});
React.render( <MyList initialItems={initialItems}/>,
document.getElementById('container') );
请注意,我将 items
道具重命名为 initialItems
,因为它清楚地表明 MyList
会改变它。这是 recommended by the documentation.
您可以在此处查看更新后的 fiddle:https://jsfiddle.net/kxrf5329/
我找到了一个很好的解决方案,使用 key 属性通过 React Hook 重新渲染。如果我们更改了子组件或 React Component 的某些部分的 key 属性,它将完全重新渲染。当您需要重新渲染 React Component 的某些部分或重新渲染子组件时,它将使用。这是一个例子。我将重新渲染整个组件。
import React, { useState, useEffect } from "react";
import { PrEditInput } from "./shared";
const BucketInput = ({ bucketPrice = [], handleBucketsUpdate, mood }) => {
const data = Array.isArray(bucketPrice) ? bucketPrice : [];
const [state, setState] = useState(Date.now());
useEffect(() => {
setState(Date.now());
}, [mood, bucketPrice]);
return (
<span key={state}>
{data.map((item) => (
<PrEditInput
key={item.id}
label={item?.bucket?.name}
name={item.bucketId}
defaultValue={item.price}
onChange={handleBucketsUpdate}
mood={mood}
/>
))}
</span>
);
};
export default BucketInput;
re-render 和 child 的一个简单选择是在每次需要 re-render 时更新唯一的键属性。
<ChildComponent key={this.state.updatedKey}/>
您可以在子组件上设置数字键,并在执行操作后触发键更改。例如
state = {
childKey: 7,
};
<ChildComponent key={this.state.childKey}/>
actionToTriggerReload = () => {
const newKey = this.state.childKey * 89; // this will make sure the key are never the same
this.setState({childKey: newKey})
}
这肯定会重新渲染 ChildComponent
在子组件中设置一个数字默认值 'key' 并重新呈现只需更改键值。
this.state = {
updatedKey: 1,
};
triggerReload = () => {
let newKey = Math.floor(Math.random() * 100); // make sure the key are never the same
this.setState({updatedKey: newKey})
}
<childComponent key={this.state.updatedKey} handlerProp = {this.onClickItemEvent} />
这对我在 reactjs class base
中重新渲染 ChildComponent 很有用
父组件(在我的示例中为MyList
)组件通过子组件(MyComponent
)呈现数组。父决定更改数组中的属性,React 触发子重新渲染的方式是什么?
我想出的只是在调整数据后 this.setState({});
在 Parent 中。这是触发更新的 hack 还是 React 方式?
JS Fiddle: https://jsfiddle.net/69z2wepo/7601/
var items = [
{id: 1, highlighted: false, text: "item1"},
{id: 2, highlighted: true, text: "item2"},
{id: 3, highlighted: false, text: "item3"},
];
var MyComponent = React.createClass({
render: function() {
return <div className={this.props.highlighted ? 'light-it-up' : ''}>{this.props.text}</div>;
}
});
var MyList = React.createClass({
toggleHighlight: function() {
this.props.items.forEach(function(v){
v.highlighted = !v.highlighted;
});
// Children must re-render
// IS THIS CORRECT?
this.setState({});
},
render: function() {
return <div>
<button onClick={this.toggleHighlight}>Toggle highlight</button>
{this.props.items.map(function(item) {
return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>;
})}
</div>;
}
});
React.render(<MyList items={items}/>, document.getElementById('container'));
您应该通过调用 setState()
并提供您想要向下传播的新道具来触发重新渲染。
如果你真的想强制更新你也可以调用 forceUpdate()
.
如果你看一下上面的例子,page, you can see that setState
is the method used to update and trigger a re-rendering. The documentation 也清楚地说明了(啊哈哈!)。
在你的情况下,我会打电话给 forceUpdate
。
编辑:正如 Jordan 在评论中提到的,最好将项目存储为状态的一部分。这样你就不必调用 forceUpdate
但你会真正更新组件的状态,因此具有更新值的常规 setState
会更好。
这里的问题是您将状态存储在 this.props
而不是 this.state
中。由于此组件正在改变 items
,因此 items
是状态并且应该存储在 this.state
中。 (这里是 good article on props vs. state。)这解决了您的渲染问题,因为当您更新 items
时,您将调用 setState
,这将自动触发重新渲染。
下面是你的组件使用 state 而不是 props 的样子:
var MyList = React.createClass({
getInitialState: function() {
return { items: this.props.initialItems };
},
toggleHighlight: function() {
var newItems = this.state.items.map(function (item) {
item.highlighted = !item.highlighted;
return item;
});
this.setState({ items: newItems });
},
render: function() {
return (
<div>
<button onClick={this.toggleHighlight}>Toggle highlight</button>
{ this.state.items.map(function(item) {
return <MyComponent key={item.id} text={item.text}
highlighted={item.highlighted}/>;
}) }
</div>
);
}
});
React.render( <MyList initialItems={initialItems}/>,
document.getElementById('container') );
请注意,我将 items
道具重命名为 initialItems
,因为它清楚地表明 MyList
会改变它。这是 recommended by the documentation.
您可以在此处查看更新后的 fiddle:https://jsfiddle.net/kxrf5329/
我找到了一个很好的解决方案,使用 key 属性通过 React Hook 重新渲染。如果我们更改了子组件或 React Component 的某些部分的 key 属性,它将完全重新渲染。当您需要重新渲染 React Component 的某些部分或重新渲染子组件时,它将使用。这是一个例子。我将重新渲染整个组件。
import React, { useState, useEffect } from "react";
import { PrEditInput } from "./shared";
const BucketInput = ({ bucketPrice = [], handleBucketsUpdate, mood }) => {
const data = Array.isArray(bucketPrice) ? bucketPrice : [];
const [state, setState] = useState(Date.now());
useEffect(() => {
setState(Date.now());
}, [mood, bucketPrice]);
return (
<span key={state}>
{data.map((item) => (
<PrEditInput
key={item.id}
label={item?.bucket?.name}
name={item.bucketId}
defaultValue={item.price}
onChange={handleBucketsUpdate}
mood={mood}
/>
))}
</span>
);
};
export default BucketInput;
re-render 和 child 的一个简单选择是在每次需要 re-render 时更新唯一的键属性。
<ChildComponent key={this.state.updatedKey}/>
您可以在子组件上设置数字键,并在执行操作后触发键更改。例如
state = {
childKey: 7,
};
<ChildComponent key={this.state.childKey}/>
actionToTriggerReload = () => {
const newKey = this.state.childKey * 89; // this will make sure the key are never the same
this.setState({childKey: newKey})
}
这肯定会重新渲染 ChildComponent
在子组件中设置一个数字默认值 'key' 并重新呈现只需更改键值。
this.state = {
updatedKey: 1,
};
triggerReload = () => {
let newKey = Math.floor(Math.random() * 100); // make sure the key are never the same
this.setState({updatedKey: newKey})
}
<childComponent key={this.state.updatedKey} handlerProp = {this.onClickItemEvent} />
这对我在 reactjs class base
中重新渲染 ChildComponent 很有用