开发者问题收集

无法访问状态对象(React useState 钩子)

2021-09-19
1003

我正在尝试访问具有名为 allMemes 的属性的状态对象。

获取 json 数据后,它将返回 100 个元素的数组。

然后另一个属性是使用此数组从长度中获取一个随机数。到目前为止,我一直收到错误“TypeError:无法读取未定义的属性(读取'url')”。

我想了解这个错误并对我的代码有一些反馈。谢谢!

const Memes = () => {
        const INITIAL_STATE = {
            topText: '',
            bottomText: '',
            randomImg:'https://i.imgflip.com/26am.jpg',
            allMemes: [],
        };
        
       
      useEffect(() => {
          fetchMemes()
      }, []);
    
      const fetchMemes = () => {
          
      console.log('loading memes data');
      try {
        fetch('https://api.imgflip.com/get_memes')
        .then(response => response.json())
        .then(response => {
         const memesArray = response.data.memes;
         console.log('memeArray', memesArray);
        setInputs(inputs =>({...inputs, allMemes: {...inputs.allMemes.memesArray}}));
        // console.log('inputs', inputs);    
        });        
      } catch (error) {
          console.log(error)
      }       
  }

 

     const handleChange = (e) => {
        const {name, value} = e.target;
        setInputs(inputs => ({...inputs, [name]: value}))    
    };
      const handleSubmit = (e) => {
        e.preventDefault();
        const randNum = Math.floor(Math.random() * inputs.allMemes.length);
        setInputs(inputs =>({...inputs, randomImg: inputs.allMemes[randNum].url}));
        // console.log('randomimg', inputs.randomImg);
        // console.log('memes', inputs.allMemes);
    };
    const [inputs, setInputs] = useState(INITIAL_STATE);
     
    return (
        <>
           <form onSubmit={handleSubmit}>
            <label htmlFor="top">Top Text:</label>
            <input type="text" name="topText" id="top" value={inputs.topText} onChange={handleChange}></input>
            <label htmlFor="btm">Bottom Text:</label>
            <input type="text" name="bottomText" id="btm" value={inputs.bottomText} onChange={handleChange}></input>
            <button>Generate</button>  
           </form>
            <div>
                <h3>{inputs.topText}</h3>
                <h3>{inputs.bottomText}</h3>
                <h3>{inputs.randomImg}</h3>
                <image src={inputs.randomImg} alt='' />
            </div>
     
        </>
    )
}

export default Memes;
2个回答

fetchMemes() 方法中,您设置了

  1. 错误的数据类型:(将数组指定为对象)

setInputs(inputs =>({...inputs, allMemes: {...inputs.allMemes.memesArray}}));
------------------------------------------^

您应该设置数组而不是对象 [] / {

    • 您没有传递获取的数据,因此您总是得到未定义的数组:

...memesArray 而不是 ...inputs.allMemes.memesArray

还将 image 更改为 img 标签

// Get a hook function
const {
  useState,
  useEffect
} = React;

const Memes = () => {
  const INITIAL_STATE = {
    topText: '',
    bottomText: '',
    randomImg: 'https://i.imgflip.com/26am.jpg',
    allMemes: [],
  };


  useEffect(() => {
    fetchMemes()
  }, []);

  const fetchMemes = () => {

    console.log('loading memes data');
    try {
      fetch('https://api.imgflip.com/get_memes')
        .then(response => response.json())
        .then(response => {
          const memesArray = response.data.memes;
          //console.log('memeArray', memesArray);
          setInputs(inputs => ({ ...inputs,
            allMemes: [ ...memesArray
            ]
          }));
          // console.log('inputs', inputs);    
        });
    } catch (error) {
      console.log(error)
    }
  }

  const handleChange = (e) => {
    const {
      name,
      value
    } = e.target;
    setInputs(inputs => ({ ...inputs,
      [name]: value
    }))
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    
    const randNum = Math.floor(Math.random() * inputs.allMemes.length);
    
    setInputs(inputs => ({ ...inputs,
      randomImg: inputs.allMemes[randNum].url
    }));
    // console.log('randomimg', inputs.randomImg);
    // console.log('memes', inputs.allMemes);
  };
  const [inputs, setInputs] = useState(INITIAL_STATE);

  return ( 
  <React.Fragment>
    <form onSubmit={handleSubmit}>
        <label htmlFor="top">Top Text:</label>
        <input type="text" name="topText" id="top" value={inputs.topText} onChange={handleChange}></input>
        <label htmlFor="btm">Bottom Text:</label>
        <input type="text" name="bottomText" id="btm" value={inputs.bottomText} onChange={handleChange}></input>
        <button>Generate</button>  
       </form>
        <div>
            <h3>{inputs.topText}</h3>
            <h3>{inputs.bottomText}</h3>
            <h3>{inputs.randomImg}</h3>
            <img src={inputs.randomImg} height={120} alt='' />
        </div>
     </React.Fragment>   
  );
};

// Render it
ReactDOM.render(<Memes />,document.getElementById("app"));
const Memes = () => {
    const INITIAL_STATE = {
        topText: '',
        bottomText: '',
        randomImg:'https://i.imgflip.com/26am.jpg',
        allMemes: [],
    };
    
   
  useEffect(() => {
      fetchMemes()
  }, []);

  const fetchMemes = () => {
      
  console.log('loading memes data');
  try {
    fetch('https://api.imgflip.com/get_memes')
    .then(response => response.json())
    .then(response => {
     const memesArray = response.data.memes;
     console.log('memeArray', memesArray);
    setInputs(inputs =>({...inputs, allMemes: {...inputs.allMemes.memesArray}}));
    // console.log('inputs', inputs);    
    });        
  } catch (error) {
      console.log(error)
  }       
}

 const handleChange = (e) => {
    const {name, value} = e.target;
    setInputs(inputs => ({...inputs, [name]: value}))    
};
  const handleSubmit = (e) => {
    e.preventDefault();
    const randNum = Math.floor(Math.random() * inputs.allMemes.length);
    setInputs(inputs =>({...inputs, randomImg: inputs.allMemes[randNum].url}));
    // console.log('randomimg', inputs.randomImg);
    // console.log('memes', inputs.allMemes);
};
const [inputs, setInputs] = useState(INITIAL_STATE);
 
return (
    
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Bourbia Brahim
2021-09-19

在 fetchMemes 函数中,当您设置输入时,请执行以下操作:

setInputs(inputs =>({...inputs, allMemes: [...inputs.allMemes.memesArray]}));

设置 allMemes 时,您应该在数组上使用扩展运算符。 但是,您正在使用一个对象。

Nishant Bhosale
2021-09-19