为什么我不能使用钩子状态在TextInput中再次编辑文本?

时间:2020-08-12 04:00:28

标签: react-native

我目前正在使用React Native开发应用程序。

此试用版应用程序的组件具有TextInput和两个按钮(ADD和DELETE)。

当我按下“添加”按钮时,将出现一个新组件。如果我按DELETE按钮,则相同的组件消失。

我用与组件索引相同的索引来控制TextInput。

屏幕就像下面的照片一样: enter image description here


在此代码中,当我编辑一些已经输入的文本时会出现一个错误。 例如:

  1. 在输入区域索引[0]中输入一些文本,然后效果很好。
  2. 按下添加按钮
  3. 再次在输入区域索引[0]中编辑已经完成的文本,然后我无法输入 文字好...

我的问题是:为什么我不能编辑已经输入的文本?


代码如下:

import React, { useState } from "react";
import { View, Text, Button, TextInput, StyleSheet } from "react-native";

function Item({ number, handleInput, handleAdd, handleDelete, index }) {
  return (
    <View style={styles.list}>
      <Text>{index}</Text>
      <TextInput
        style={{ borderWidth: 1 }}
        value={number[index]}
        onChangeText={(text) => {
          handleInput(index, text);
        }}
      ></TextInput>
      <Button
        title="ADD"
        onPress={() => {
          handleAdd();
        }}
      />
      <Button
        title="DELETE"
        onPress={() => {
          handleDelete(index);
        }}
      />
    </View>
  );
}

export default function SOFStateArray() {
  const [count, setCount] = useState(1);
  const [number, setNumber] = useState([]);

  function handleAdd() {
    setCount((v) => v + 1);
  }

  function handleDelete(index) {
    setCount((v) => v - 1);
    setNumber((v) => {
      const ret = v.slice();
      ret.splice(index, 1);
      return ret;
    });
  }

  function handleInput(index, text) {
    setNumber((v) => {
      v.splice(index, 1, text);
      return v;
    });
  }

  // function handleInput(index, text) {
  //   setNumber((v) => {
  //     const ret = v.slice();
  //     ret.splice(index, 1, text);
  //     return ret;
  //   });
  // }

  return (
    <View>
      {Array.from({ length: count }, (_, i) => (
        <Item
          number={number}
          handleInput={handleInput}
          handleAdd={handleAdd}
          handleDelete={handleDelete}
          key={i + "-" + number}
          index={i}
        />
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  list: {
    margin: 10,
    padding: 10,
    backgroundColor: "#ddd",
  },
});

这是第一个修改后的代码(使用环来制作组件):

import React, { useState } from "react";
import { View, Text, Button, TextInput, StyleSheet } from "react-native";

function Item({ number, handleInput, handleAdd, handleDelete, index }) {
  return (
    <View style={styles.list}>
      <Text>{index}</Text>
      <TextInput
        style={{ borderWidth: 1 }}
        value={String(number)}
        onChangeText={(text) => {
          console.log(text);
          handleInput(index, text);
        }}
      ></TextInput>
      <Button
        title="ADD"
        onPress={() => {
          handleAdd();
        }}
      />
      <Button
        title="DELETE"
        onPress={() => {
          handleDelete(index);
        }}
      />
    </View>
  );
}

export default function SOFStateArray() {
  const [count, setCount] = useState(1);
  const [numbers, setNumber] = useState([0]);

  function handleAdd() {
    setCount((v) => v + 1);
  }

  function handleDelete(index) {
    setCount((v) => v - 1);
    setNumber((v) => {
      const ret = v.slice();
      ret.splice(index, 1);
      return ret;
    });
  }

  function handleInput(index, text) {
    setNumber((v) => {
      v.splice(index, 1, text);
      return v;
    });
  }

  // function handleInput(index, text) {
  //   setNumber((v) => {
  //     const ret = v.slice();
  //     ret.splice(index, 1, text);
  //     return ret;
  //   });
  // }

  return (
    <View>
      {numbers.map((number, i) => (
        <Item
          number={number}
          handleInput={handleInput}
          handleAdd={handleAdd}
          handleDelete={handleDelete}
          key={i + "-" + number}
          index={i}
        />
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  list: {
    margin: 10,
    padding: 10,
    backgroundColor: "#ddd",
  },
});

节点:12.18.3

反应原生:4.10.1

博览会:3.22.3

1 个答案:

答案 0 :(得分:1)

JavaScript数组拼接修改原始数组。这意味着数组变量本身不会改变。我建议您克隆原始数组,拼接克隆的数组并返回它。之所以可以这样做是因为react会将旧道具与新道具进行比较,并且仅在道具不同时才重新渲染组件。就目前而言,即使您从数组中删除了一个项目,数组变量也没有改变,也没有重新呈现组件。

import React from 'react';
import {
  SafeAreaView,
  StyleSheet,
  View,
  Text,
  StatusBar,
  TextInput,
  Button,
} from 'react-native';

function Item({text, handleInput, handleAdd, handleDelete, index}) {
  return (
    <View style={styles.list}>
      <Text>{index}</Text>
      <TextInput
        style={{borderWidth: 1}}
        value={text}
        onChangeText={(t) => {
          handleInput(index, t);
        }}
      />
      <Button
        title="ADD"
        onPress={() => {
          handleAdd();
        }}
      />
      <Button
        title="DELETE"
        onPress={() => {
          handleDelete(index);
        }}
      />
    </View>
  );
}

class App extends React.Component {
  state = {
    texts: [''],
  };

  handleAdd = () => {
    const {texts} = this.state;
    this.setState({texts: [...texts, '']});
  };

  handleDelete = (index) => {
    const texts = [...this.state.texts];
    texts.splice(index, 1);
    this.setState({texts: texts});
  };

  handleInput = (index, text) => {
    const {texts} = this.state;
    texts[index] = text;
    this.setState({texts});
  };

  render() {
    const {texts} = this.state;

    return (
      <>
        <StatusBar barStyle="dark-content" />
        <SafeAreaView>
          <View style={styles.body}>
            {texts.map((text, i) => (
              <Item
                key={'' + i}
                text={text}
                handleInput={this.handleInput}
                handleAdd={this.handleAdd}
                handleDelete={this.handleDelete}
                index={i}
              />
            ))}
          </View>
        </SafeAreaView>
      </>
    );
  }
}

const styles = StyleSheet.create({
  body: {
    backgroundColor: '#ffffff',
  },
});

export default App;