简体   繁体   English

当 state 在 React 中更新时,道具不会更新

[英]Props don't update when state updates in React

I'm passing some values from my state in the App component to the GetWordContainer component as props.我正在将 App 组件中的 state 中的一些值作为道具传递给 GetWordContainer 组件。 With these props, I set the state in my child component.使用这些道具,我在我的子组件中设置了 state。 However, the state in GetWordContainer only updates once.但是,GetWordContainer 中的 state 只更新一次。 How can I have the state in the child component continue to update when the state in App.js changes?当 App.js 中的 state 发生变化时,如何让子组件中的 state 继续更新?

App.js应用程序.js

class App extends Component {

  state = {
    redirect: {},
    word: '',
    error: '',
    info: [],
    partOfSpeech: [],
    versions: [],
    shortdef: "",
    pronunciation: "",
  }

  setRedirect = redirect =>{{
    this.setState({redirect})
  }
  // console.log(this.state.redirect);
  console.log(this.state.word);
}
  

  handleUpdate = values => 
    this.setState({...values})
    


render() {
    return (
      <>
        <Route 
          render={ routeProps => <Redirector redirect={this.state.redirect} setRedirect={this.setRedirect} {...routeProps} />}
        />
        <header>
          <nav>
            <Link to='/'>My Dictionary</Link>
          </nav>
        </header>

        <main>
        <Route
            render = { routeProps =>
              !routeProps.location.state?.alert ? '' :
              <div>
                { routeProps.location.state.alert }
              </div>
            }
          />
          <Switch>
            <Route exact path="/" render={ routeProps => 
              <Home 
                setRedirect={this.setRedirect} 
                handleUpdate={this.handleUpdate} 
                {...routeProps} />} 
              />
            <Route exact path="/definition/:word" render={routeProps => 
              <GetWordContainer 
                setRedirect={this.setRedirect}
                handleUpdate={this.handleUpdate}
                word={this.state.word} 
                partOfSpeech={this.state.partOfSpeech}
                versions={this.state.versions}
                shortdef={this.state.shortdef}
                pronunciation={this.state.pronunciation}
                {...routeProps} />} 
              />
          </Switch>
        </main>
      </>
    );
  }
}

GetWordContainer.js获取WordContainer.js

class GetWordContainer extends Component {

//this state only updates once 
state = {
  word: this.props.word,
  info: this.props.info,
  partOfSpeech: this.props.parOfSpeech,
  versions: this.props.versions,
  shortdef: this.props.shortdef,
  pronunciation: this.props.pronunciation,
}


render (){

  return (

      <div>
        <Search
          handleUpdate={this.props.handleUpdate}
          setRedirect={this.props.setRedirect}
        />
        <div>
             {this.state.word}
        </div>
        <div>
             {this.state.partOfSpeech}
        </div>
        <div>
             {this.state.versions.map((v, i) => <div key={i}>{v}</div>)}
        </div>
        <div>
             {this.state.pronunciation}
        </div>
        <div>
             {this.state.shortdef}
        </div>
      </div>
  );
  }
}

The issue you're facing is that the state value in the GetWordContainer component is instantiated on the initial render.您面临的问题是GetWordContainer组件中的state值是在初始渲染时实例化的。 There are exceptions but in general, React will reuse the same component across renders when possible.有例外,但一般来说,React 会在可能的情况下跨渲染重用相同的组件。 This means the component is not re-instantiated, so the state value does not change across re-renders.这意味着组件不会重新实例化,因此state值不会在重新渲染时发生变化。

One solution to this problem is to use the appropriate lifecycle method to handle when the component re-renders and update state appropriately: getDerivedStateFromProps此问题的一种解决方案是使用适当的生命周期方法来处理组件重新渲染并适当更新 state: getDerivedStateFromProps

However, since it appears you want to render the props directly, I would recommend avoiding state entirely in GetWordContainer .但是,由于您似乎想直接渲染道具,我建议您在 GetWordContainer 中完全避免GetWordContainer

For example:例如:

class GetWordContainer extends Component {
  render() {
    return (
      <div>
        <Search
          handleUpdate={this.props.handleUpdate}
          setRedirect={this.props.setRedirect}
        />
        <div>{this.props.word}</div>
        <div>{this.props.partOfSpeech}</div>
        <div>
          {this.props.versions.map((v, i) => (
            <div key={i}>{v}</div>
          ))}
        </div>
        <div>{this.props.pronunciation}</div>
        <div>{this.props.shortdef}</div>
      </div>
    );
  }
}

Your constructor lifecycle method runs only once - during the initialisation of the component.您的构造函数生命周期方法只运行一次 - 在组件初始化期间。 If you are expecting new data from parent component, you can re-render your child by using componentDidUpdate() or getDerivedStateFromProps .如果您期望来自父组件的新数据,您可以使用componentDidUpdate()getDerivedStateFromProps重新渲染您的孩子。

componentDidUpdate(prevProps) {
  if (prevProps.word || this.props.word) {
   this.setState({
     word
   })
  }
}

I notice that your child component is not manipulating the props, it is just a display-only container.我注意到您的子组件没有操纵道具,它只是一个仅显示的容器。 Why don't you just pass the props and display it directly rather than taking the longest route?为什么不直接通过道具直接展示,而不是走最长的路线呢? Your child component can be a functional component:您的子组件可以是功能组件:


const GetWordContainer = (props) => {
  return (
      <div>
        <Search
          handleUpdate={props.handleUpdate}
          setRedirect={props.setRedirect}
        />
        <div>
             {props.word}
        </div>
        <div>
             {props.partOfSpeech}
        </div>
        <div>
             {props.versions.map((v, i) => <div key={i}>{v}</div>)}
        </div>
        <div>
             {props.pronunciation}
        </div>
        <div>
             {props.shortdef}
        </div>
      </div>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM