根据另一个组件的状态更改 React 组件可见性



我创建了以下 React 组件。它使用输入框来接受用户对谜语的回答。一旦用户的输入与所需的答案匹配,输入框就会变为只读(使用它们的方式有点奇怪(。它还有一个"isHidden"道具来确定谜语是否被渲染。

class Riddle extends React.Component {
constructor(props) {
super(props);
this.answer = props.answer.toUpperCase();
this.state = {
text: "",
isAnswered: false
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
let userInput = event.target.value.toUpperCase();
if (userInput == this.answer) {
this.setState({
text: userInput,
isAnswered: true
});
} else {
this.setState({
text: userInput,
isAnswered: false
});
}
}
render() {
if (this.props.isHidden) {
return <div></div>;
} else {
return (
<div>
<p>{this.props.prompt}</p>
<input type="text" value={this.state.text} 
readOnly={this.state.isAnswered}></input>
</div>
);
}
}
}

这是在实践中:

function App() {
return (
<div>
<Riddle prompt='The first three letters in the alphabet.' answer="abc" isHidden="false"/>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));

我想做的是按顺序排列一堆这样的谜语,但只有在解决前一个谜语时才可以看到谜语。问题是我不知道如何导致可见性更新发生。

我已经阅读了有关将状态从子组件提升到父组件的信息,并且我尝试查看是否可以创建一个Riddle作为其子组件的RiddleSequence组件,并RiddleSequence管理可见性。我的问题是,目前无论是否解决,它都是Riddle状态的一部分,我不知道RiddleSequence如何读取该信息,因为子状态应该保持隐藏状态。这似乎是封装Riddle功能的合理方法,但考虑到我的目标,也许我错了。

我还考虑过让Riddle成为他们所依赖的其他谜语的孩子,因为我可以将状态/道具传递给孩子:

<Riddle prompt="first riddle"...>
<Riddle prompt="depends on first riddle"...>
<Riddle prompt="depends on second riddle"...>
</Riddle>
</Riddle>
</Riddle>

但是,如果我有一个包含 100 个谜语的应用程序,这似乎变得荒谬。这也降低了扩展功能集的灵活性(例如使一个谜语依赖于一组 3 个谜语(。

如何使Riddle组件的可见性取决于其他谜语的状态?

一个简单的解决方案是像你说的那样有一个容器组件:

class Riddle extends Component {
constructor(props) {
this.state = {
text: ''
}
this.answer = props.answer.toUpperCase()
}
handleChange = event => {
const userInput = event.target.value.toUpperCase()
const callback = userInput == this.answer ? this.props.onSolved : undefined
this.setState({ text: userInput }, callback)
}
render() {
const { text, isAnswered } = this.state
const { prompt } = this.props
if (this.props.isHidden) {
return null
}
return (
<div>
<p>{prompt}</p>
<input type="text" value={text} readOnly={isAnswered}></input>
</div>
)
}
}

容器应保持这样的可见性:

class RiddleSequence extends Component {
state = {}
riddles = [
{
id: 1,
prompt: 'The first three letters in the alphabet.',
answer: 'abc',
prev: null
},
{
id: 2,
prompt: 'The last three letters in the alphabet.',
answer: 'xyz',
prev: 1
}
]
render() {
return (
<div>
{this.riddles.map(r => {
const { id, prev } = r
const visible = !prev || this.state[prev]
return (
<Riddle
key={id}
isHidden={!visible}
onSolved={() => this.setState({ [r.id]: true })}
{...r}
/>
)
})}
</div>
)
}
}

最新更新