Je souhaite afficher / masquer une partie de JSX en fonction de la propriété d'état isCommentShown
. Mais comme cette partie est à l'intérieur d'une boucle de carte, isCommentShown
agit pour tous les éléments mappés et pas seulement pour celui en cours. Ainsi, lorsque je toggleComment
, chaque commentaire à l'intérieur d'une boucle est affiché / masqué. J'imagine que cela peut être résolu en déplaçant tout dans un composant séparé car chaque composant a son propre état. Mais je me demande si je peux résoudre ce problème sans cela.
const SearchResults = () => { const [isCommentShown, setIsCommentShown] = useState(false); const toggleComment = () => { setIsCommentShown(!isCommentShown); }; return ( <> {props.search_results.map(obj => <div key={obj.id}> { obj.comment ? <img onClick={toggleComment}/> : null } <div>{obj.text}</div> { isCommentShown ? <p>{obj.comment}</p> : null } </div> )} </> ); };
3 Réponses :
Au lieu de stocker vrai ou faux, vous devez stocker l'ID de commentaire à afficher à condition que vous ne souhaitiez afficher qu'un seul commentaire à la fois. Il est important d'identifier de manière unique l'élément à développer
const SearchResults = () => { const [commentShown, setCommentShown] = useState(''); const toggleComment = (id) => { setCommentShown(prev => prev.commentShown !== id? id: ''); }; return ( <> {props.search_results.map(obj => <div key={obj.id}> { obj.comment ? <img onClick={() => toggleComment(obj.id)}/> : null } <div>{obj.text}</div> { commentShown === obj.id ? <p>{obj.comment}</p> : null } </div> )} </> ); };
Si vous avez besoin d'ouvrir plusieurs commentaires simultanément, vous pouvez maintenir une carte des identifiants ouverts
const SearchResults = () => { const [commentShown, setCommentShown] = useState({}); const toggleComment = (id) => { setCommentShown(prev => Boolean(!prev[id]) ? {...prev, [id]: true} : {...prev, [id]: false}); }; return ( <> {props.search_results.map(obj => <div key={obj.id}> { obj.comment ? <img onClick={() => toggleComment(obj.id)}/> : null } <div>{obj.text}</div> { commentShown[id] ? <p>{obj.comment}</p> : null } </div> )} </> ); };
Utilisez l'id pour cibler la bascule sur le commentaire souhaité.
Plus précisément, utilisez l'état pour stocker les valeurs afficher / masquer, et transmettez l'id à l'événement onclick pour préciser le commentaire à activer. Cela devrait faire l'affaire:
class SearchResults extends React.Component { constructor(props) { super(props); this.state = {}; for (let result of props.search_results) { this.state[`${result.id}IsShown`] = true; } } toggleComment(id) { let key = `${result.id}IsShown`; this.setState({[key]: !this.state[key]}); } render() { return ( <> {this.props.search_results.map(result => <div key={result.id}> { result.comment ? <img onClick={() => toggleComment(result.id)}/> : null } <div>{result.text}</div> { isCommentShown ? <p>{obj.comment}</p> : null } </div> )} </> ); } }
Vous pouvez utiliser le hook useState
pour créer un objet qui conservera tous les identifiants des résultats de recherche sous forme de clés et une valeur booléenne indiquant si le commentaire doit être affiché ou non.
Exemple
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>
const { useState, Fragment } = React; const SearchResults = props => { const [shownComments, setShownComments] = useState({}); const toggleComment = id => { setShownComments(prevShownComments => ({ ...prevShownComments, [id]: !prevShownComments[id] })); }; return ( <Fragment> {props.search_results.map(obj => ( <div key={obj.id}> {obj.comment ? ( <button onClick={() => toggleComment(obj.id)}>Toggle</button> ) : null} <div>{obj.text}</div> {shownComments[obj.id] ? <p>{obj.comment}</p> : null} </div> ))} </Fragment> ); }; ReactDOM.render( <SearchResults search_results={[ { id: 0, text: "Foo bar", comment: "This is rad" }, { id: 1, text: "Baz qux", comment: "This is nice" } ]} />, document.getElementById("root") );
Eh bien, à quel commentaire
isCommentShown
est censé être attribué?