【问题标题】:React read input values from multiple input text fieldsReact 从多个输入文本字段中读取输入值
【发布时间】:2021-02-21 11:05:05
【问题描述】:

您好,我有一个使用 imgflip 公共 api 的小型 meme 编辑器。我通常使用 Angular 进行开发,但我正在尝试学习 react,所以我现在有点迷茫。

在我的项目中,当我加载页面时,我会得到一份所有可用 meme 模板的列表,然后当您选择一个模板时,您将拥有该模板和每个 meme 文本行的一个文本字段。每个模板上输入文本的数量都会发生变化,这就是我卡住的地方。

这个想法是获取所有输入文本值,将其发送到 api 并将生成的 meme 显示给用户。

这是我现在的代码:

App.js

import { useEffect, useState } from 'react';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";
import memeService from './services/memeService';
import Meme from './components/Meme';
import './App.css';
import Editor from './components/Editor';


function App() {

  const [memes, setMemes] = useState([]);

  useEffect(() => {
    (async function getData() {
      await getMemes();
    })();
  }, []);

  const getMemes = async () => {
    const results = await memeService.getMemes();
    setMemes(results.data.data.memes);
  }

  return (
    <>
      <Router>
        <Switch>
        <Route path="/:id/edit" children={<Editor />} />
          <Route path="/">
            <div className='container'>
              {memes.map(meme => <Meme key={meme.id} meme={meme} />)}
            </div>
          </Route>
        </Switch>
        
      </Router>
      
    </>
  )
}

export default App;

Editor.js

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import memeService from './../services/memeService';

const Editor = () => {

    const [meme, setMeme] = useState({});
    const {id } = useParams()

    const getMeme = async () => {
        setMeme(await memeService.getMeme(id));
    }

    useEffect(getMeme, [id]);

    const TextBox = () => {

        const inputs = [];

        for(let i = 0; i < meme.box_count; i++){
            inputs.push(<input key={i} type='text' />);
        }

        return (
            <>
                {inputs.map(input => {return input})}
            </>
        )
    }

    const generateMeme = () => {
        console.log('generating meme');
    }

    return (
        <>
            <div className='container'>
                <div className='meme'>
                    <img alt={meme.name} src={meme.url} />
                </div>
                <div className='text'>
                    <TextBox />
                </div>
            </div>
            <button onClick={generateMeme}>Save</button>
        </>
    )

}

export default Editor;

我对渲染输入文本字段的 TextBox 函数并不感到自豪,但现在我最关心的是如何让它工作。

我被卡住的地方是 Editor.js 我需要获取编辑器上输入文本字段中的所有文本,以将其发送到 API。在我遵循的其他教程中,我使用应用程序的状态使用 onChange 事件进行了操作,因此当用户在文本上输入时,状态会更新,当单击提交按钮时,我只使用当前状态,但在这种情况下我不因为有多个不同的输入,所以看不到它的可能。

顺便说一下,这是我正在使用的 API:https://imgflip.com/api

【问题讨论】:

    标签: javascript reactjs api input


    【解决方案1】:

    首先,您需要跟踪输入中的值,方法是向TextBox 添加一个数组并控制输入。

    其次,您需要将值传递给父级。为此,您可以添加一个处理程序方法,该方法会将值记住到 ref 中,例如

    const values = useRef()
    handleChange(newValues){
       values.current(newValues)
    }
    

    然后你将handleChange 作为prop 传递并在setValues 之后调用它。在提交时,您将在 values.current

    中获得您的值

    完整的TextBox

    const TextBox = (props) => {
    const [values, setValues] = useState([])
    const inputs = [];
    
    useEffect(()=>{
      props.onChange && props.onChange(values)
    }, [values])
    
    function handleInput(e, i)
    {
      setValues(v =>{
        const temp=[...v];
        temp[i]=e.target.value;
        return temp})
    }
    
    for(let i = 0; i < meme.box_count; i++){
      inputs.push(<input key={i} type='text' value={values[i]} onChange={(e) => handleInput(e,i) } />);
    }
    
    return (inputs)
    }
    

    【讨论】:

    • 我实施了您提出的解决方案,但将 ':' 替换为 '.'在将输入值添加到值数组时,但是当我输入任何输入文本时,我得到一个“无法读取未定义的属性‘目标’”错误
    • @kiewlovsky 是的,语法有点,看看更新
    • 感谢 Nadia 现在按预期工作,必须向 useEffect 函数添加道具,但您的代码运行良好
    • 一个小问题,关于 setValue 函数,你为什么使用这个表达式 'v =>'?有了这个你可以处理函数内部的当前状态?
    • 是的,没错。在这种情况下,这更像是一种预防措施,您可以在 setValues 之外基于 values 创建一个新状态,但通常最好将回调传递给 setState 以获得最新的状态形式 React
    猜你喜欢
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 1970-01-01
    • 2017-09-07
    相关资源
    最近更新 更多