状态更改后反应组件不呈现
React component not rendering after state change
正如标题所说,当我的组件中的状态发生变化时,子组件不会重新呈现。
class App extends Component {
constructor() {
super()
this.state = {
url: ""
}
this.handleWorkerSelect = this.handleWorkerSelect.bind(this)
}
handleWorkerSelect(url) {
this.setState({ url })
}
render() {
return (
<div className="App">
<Workers className="workers" handleClick={this.handleWorkerSelect}/>
<HermesWorker url={this.state.url}/>
</div>
)
}
}
const Workers = (props) => {
return (
<div>
<button onClick={() => props.handleClick("http://localhost:5000/api")}>Worker 1</button>
<button onClick={() => props.handleClick("http://localhost:2000/api")}>Worker 2</button>
</div>
)
}
export default App
这里是hermesworker.js
class HermesWorker extends Component {
constructor() {
super()
this.state = {
items: [],
visited: [{name: "This Drive", path: "@back", root: ""}]
}
this.handleFolderClick = this.handleFolderClick.bind(this)
this.handleFileClick = this.handleFileClick.bind(this)
}
componentDidMount() {
if (this.props.url.length === 0) return
fetch(this.props.url)
.then(res => res.json())
.then(items => this.setState({ items }))
}
render() {
const folders = this.state.items.map((item) => {
if (!item.isfile) {
return <Card handleClick={this.handleFolderClick} root={item.root} path={item.path} isfile={item.isfile} name={item.name} size={item.size}/>
}
})
const files = this.state.items.map((item) => {
if (item.isfile) {
return <Card handleClick={this.handleFileClick} root={item.root} path={item.path} isfile={item.isfile} name={item.name} s ize={item.size}/>
}
})
const pathButtons = this.state.visited.map((item) => {
return <PathButton handleClick={this.handleFolderClick} root={item.root} path={item.path} name={item.name}/>
})
return (
<div>
{pathButtons}
<div className="flex-container">
{folders}
{files}
</div>
</div>
)
}
}
本质上,问题是 HermesWorker 组件没有被重新渲染以使用新的 url 道具。我不确定为什么会发生这种情况,因为例如,在 hermesworker 中,它呈现其他子组件,这些子组件在状态更改期间确实会重新呈现。
如有任何信息,我们将不胜感激
编辑已更新以添加 hermes worker,该文件超过 100 行,所以我删掉并仅粘贴了我认为对问题很重要的内容,如果需要可以提供更多内容
我测试了该代码,它似乎工作正常。能否提供HermesWorker组件中设置了什么?
编辑:您需要在组件更新时使用 setState
设置您的状态。为此,您可以查找 componentDidUpdate
,它会在每次更新时 运行。这与 componentDidMount
不同,后者(希望)会 运行 一次,然后组件可能会更新并重新渲染,但重新渲染不会被视为 "mount"。所以你可以试试这个:
constructor(props) {
super(props);
this.state = {
url: '',
items: [],
visited: [{name: "This Drive", path: "@back", root: ""}]
}
this.fetchData = this.fetchData.bind(this);
}
componentDidMount() {
//Mount Once
}
componentDidUpdate(prevProps, prevState) {
if (this.state.url !== this.props.url) {
this.setState({url: this.props.url});
// Url state has changed.
}
if(prevState.url !== this.state.url){
//run your fetch
this.fetchData();
}
}
fetchData(){
if (this.props.url.length === 0) return
fetch(this.props.url)
.then(res => res.json())
.then(items => this.setState({ items }));
}
注意:我将提取移到了它自己的函数中,但这完全取决于您。
另请注意,我向状态添加了 url。确保设置好道具以避免意外行为。
编辑 2:componentDidUpdate
会将 prevProps
和 prevState
作为参数交给您。使用 prevProps
,您可以访问 您在上一次更新中获得的任何道具 ,而使用 prevState
,您可能会猜到,您可以访问 无论你的状态是什么 上次更新。 "on the previous update" 我的意思是在执行更新之前。
正如标题所说,当我的组件中的状态发生变化时,子组件不会重新呈现。
class App extends Component {
constructor() {
super()
this.state = {
url: ""
}
this.handleWorkerSelect = this.handleWorkerSelect.bind(this)
}
handleWorkerSelect(url) {
this.setState({ url })
}
render() {
return (
<div className="App">
<Workers className="workers" handleClick={this.handleWorkerSelect}/>
<HermesWorker url={this.state.url}/>
</div>
)
}
}
const Workers = (props) => {
return (
<div>
<button onClick={() => props.handleClick("http://localhost:5000/api")}>Worker 1</button>
<button onClick={() => props.handleClick("http://localhost:2000/api")}>Worker 2</button>
</div>
)
}
export default App
这里是hermesworker.js
class HermesWorker extends Component {
constructor() {
super()
this.state = {
items: [],
visited: [{name: "This Drive", path: "@back", root: ""}]
}
this.handleFolderClick = this.handleFolderClick.bind(this)
this.handleFileClick = this.handleFileClick.bind(this)
}
componentDidMount() {
if (this.props.url.length === 0) return
fetch(this.props.url)
.then(res => res.json())
.then(items => this.setState({ items }))
}
render() {
const folders = this.state.items.map((item) => {
if (!item.isfile) {
return <Card handleClick={this.handleFolderClick} root={item.root} path={item.path} isfile={item.isfile} name={item.name} size={item.size}/>
}
})
const files = this.state.items.map((item) => {
if (item.isfile) {
return <Card handleClick={this.handleFileClick} root={item.root} path={item.path} isfile={item.isfile} name={item.name} s ize={item.size}/>
}
})
const pathButtons = this.state.visited.map((item) => {
return <PathButton handleClick={this.handleFolderClick} root={item.root} path={item.path} name={item.name}/>
})
return (
<div>
{pathButtons}
<div className="flex-container">
{folders}
{files}
</div>
</div>
)
}
}
本质上,问题是 HermesWorker 组件没有被重新渲染以使用新的 url 道具。我不确定为什么会发生这种情况,因为例如,在 hermesworker 中,它呈现其他子组件,这些子组件在状态更改期间确实会重新呈现。
如有任何信息,我们将不胜感激
编辑已更新以添加 hermes worker,该文件超过 100 行,所以我删掉并仅粘贴了我认为对问题很重要的内容,如果需要可以提供更多内容
我测试了该代码,它似乎工作正常。能否提供HermesWorker组件中设置了什么?
编辑:您需要在组件更新时使用 setState
设置您的状态。为此,您可以查找 componentDidUpdate
,它会在每次更新时 运行。这与 componentDidMount
不同,后者(希望)会 运行 一次,然后组件可能会更新并重新渲染,但重新渲染不会被视为 "mount"。所以你可以试试这个:
constructor(props) {
super(props);
this.state = {
url: '',
items: [],
visited: [{name: "This Drive", path: "@back", root: ""}]
}
this.fetchData = this.fetchData.bind(this);
}
componentDidMount() {
//Mount Once
}
componentDidUpdate(prevProps, prevState) {
if (this.state.url !== this.props.url) {
this.setState({url: this.props.url});
// Url state has changed.
}
if(prevState.url !== this.state.url){
//run your fetch
this.fetchData();
}
}
fetchData(){
if (this.props.url.length === 0) return
fetch(this.props.url)
.then(res => res.json())
.then(items => this.setState({ items }));
}
注意:我将提取移到了它自己的函数中,但这完全取决于您。
另请注意,我向状态添加了 url。确保设置好道具以避免意外行为。
编辑 2:componentDidUpdate
会将 prevProps
和 prevState
作为参数交给您。使用 prevProps
,您可以访问 您在上一次更新中获得的任何道具 ,而使用 prevState
,您可能会猜到,您可以访问 无论你的状态是什么 上次更新。 "on the previous update" 我的意思是在执行更新之前。