当状态在React中更新时,道具不更新

时间:2020-07-21 00:46:06

标签: reactjs state jsx react-props

我正在将一些值从我在App组件中的状态传递给props的GetWordContainer组件。借助这些道具,我在子组件中设置了状态。但是,GetWordContainer中的状态仅更新一次。当App.js中的状态更改时,子组件中的状态如何继续更新?

App.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

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>
  );
  }
}

2 个答案:

答案 0 :(得分:2)

您面临的问题是initialize()组件中的state值是在初始渲染时实例化的。有例外,但通常,React将尽可能在渲染之间重用相同的组件。这表示该组件未重新实例化,因此GetWordContainer的值在重新渲染时不会改变。

此问题的一种解决方案是使用适当的生命周期方法来处理组件何时重新渲染并适当更新状态:getDerivedStateFromProps

但是,由于您似乎想直接渲染道具,所以我建议完全避免使用state中的状态。

例如:

GetWordContainer

答案 1 :(得分:1)

您的构造函数生命周期方法仅运行一次-在组件初始化期间。如果您希望从父组件获得新数据,则可以使用componentDidUpdate()getDerivedStateFromProps重新渲染孩子。

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

我注意到您的子组件没有操纵道具,它只是一个仅用于显示的容器。为什么不通过道具直接展示而不是走最长的路线呢?您的子组件可以是功能组件:


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>
  );
}