如何使用状态将类组件重写为功能组件

时间:2020-08-13 09:59:29

标签: reactjs react-native

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

我有一个使用状态的类组件,并且想要将其重写为一个功能组件,以便与上一个类组件使用相同的内容。

但是我不能重写它……当然,原始代码(类组件)可以很好地工作

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

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

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


我无法解决的问题是在输入区域中输入一些文本。

输入一些文本时,我只能输入几个文本,并且输入区域视图不反映收集值...

当我重新编写功能代码时如何解决此问题?


这是原始代码(类组件):

    import React from "react";
    import { StyleSheet, View, Text, 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 RewriteClass 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 (
          <View>
            {texts.map((text, i) => (
              <Item
                key={"" + i}
                text={text}
                handleInput={this.handleInput}
                handleAdd={this.handleAdd}
                handleDelete={this.handleDelete}
                index={i}
              />
            ))}
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      list: {
        backgroundColor: "#ddd",
        margin: 10,
        padding: 10,
      },
    });
    
    export default RewriteClass;

这是到目前为止我尝试重写的代码(功能组件):

import React, { useState } from "react";
import { StyleSheet, View, Text, 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>
  );
}

export default function RewriteFunction() {
  const [texts, setTexts] = useState([""]);

  //handleAdd = () => {
  const handleAdd = () => {
    setTexts((v) => {
      const ret = [...v, ""];
      return ret;
    });
  };

  //handleDelete = (index) => {
  const handleDelete = (index) => {
    setTexts((v) => {
      const ret = [...v];
      ret.splice(index, 1);
      return ret;
    });
  };

  //handleInput = (index, text) => {
  const handleInput = (index, text) => {
    setTexts((v) => {
      const ret = v;
      ret[index] = text;
      return ret;
    });
  };

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

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

节点:12.18.3

反应原生:4.10.1

博览会:3.22.3


1 个答案:

答案 0 :(得分:2)

问题是子组件未更新。我们将不得不为其分配专用状态,该状态仅使用来自props的值进行初始化:

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

export function Item({ text, handleInput, handleAdd, handleDelete, index }) {
  const [inputValue, setInputValue] = React.useState(text);

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

export default function RewriteFunction() {
  const [texts, setTexts] = useState([""]);

  //handleAdd = () => {
  const handleAdd = () => {
    setTexts((v) => {
      const ret = [...v, ""];
      return ret;
    });
  };

  //handleDelete = (index) => {
  const handleDelete = (index) => {
    setTexts((v) => {
      const ret = [...v];
      ret.splice(index, 1);
      return ret;
    });
  };

  //handleInput = (index, text) => {
  const handleInput = (index, text) => {
    let t = texts;
    t[index] = text;
    setTexts(t);
  };

  return (
    <View>
      {texts.map((text, i) => (
        <Item
          key={text + i.toString()}
          text={texts[i]}
          handleInput={handleInput}
          handleAdd={handleAdd}
          handleDelete={handleDelete}
          index={i}
        />
      ))}
    </View>
  );
}

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