Hadid
Hadid

Reputation: 45

Wrong rendering when using map to render from an array in React

In this issue, I have an array of objects like:

const sampleCards = [
        {userName:'user1',avatarURL:'../avatar/role11.jpg',mainPageURL:'/',isFollowed:true},
        {userName:'user2',avatarURL:'../avatar/role12.jpg',mainPageURL:'/',isFollowed:true},
        {userName:'user3',avatarURL:'../avatar/role13.jpg',mainPageURL:'/',isFollowed:false},
    ];

then I used map() to render this array:

export default function SearchBar(){
    
    return (
        <div className='searchBar'> 
            {sampleCards.map((result)=>{
                return (
                    <SearchResultCard result={result}/>                  
                );
            })}
        </div>
    );
}

A SearchResultCard component be like:

export default function SearchResultCard(result){

    const [isFollowed,setIsFollowed] = useState(result.isFollowed);
    const handleFollowingClicked = ()=>{
        setIsFollowed(false);
    };
    const handleFollowClicked=()=>{
        setIsFollowed(true);
    };

    useEffect(()=>{console.log(result.userName)});

    return (
        
            <div className="search-result-card">
                <Link to={result.mainPageURL}>
                    <div className="search-result-card-left">
                        <img src={result.avatarURL} alt={result.userName} className="search-result-img"/>
                        <p>{result.userName}</p>
                    </div>
                </Link>
                {isFollowed ? (
                    <button className="following-button" onClick={handleFollowingClicked}>Following</button> 
                ):(
                    <button className="follow-button" onClick={handleFollowClicked}>Follow</button>
                )}
            </div>
       
    );
}

The problem is that values in result seem not been passed to so it just ends with a 'Follow' button while other elements are not rendered

Upvotes: 2

Views: 85

Answers (1)

adiga
adiga

Reputation: 35222

The parameter in SearchResultCard is the entire props object. This has a property called result. You need to destructure to get the result prop:

function SearchResultCard({ result }){ ... }

Here's a snippet:

const {useState} = React;

const sampleCards = [
  { userName:'user1', isFollowed:true },
  { userName:'user2', isFollowed:true },
  { userName:'user3', isFollowed:false },
];

 function SearchResultCard({ result }){
 
    const [isFollowed,setIsFollowed] = useState(result.isFollowed);
    const handleFollowingClicked = _ => setIsFollowed(false);
    const handleFollowClicked= _ => setIsFollowed(true);

  return (
            <div className="search-result-card">
              {isFollowed 
                ? ( <button onClick={handleFollowingClicked}>Following</button>)
                : ( <button onClick={handleFollowClicked}>Follow</button>)
              }
            </div>
    );
}

function Example(){
    return (
        <div className='searchBar'> 
            {sampleCards.map((result)=>{
                return (
                    <SearchResultCard key={result.userName} result={result}/>             
                );
            })}
        </div>
    );
}


// Render it
ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <Example />
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

Upvotes: 2

Related Questions