【问题标题】:How to make fetch request at a parent component如何在父组件上发出 fetch 请求
【发布时间】:2022-01-22 10:10:08
【问题描述】:

我有一个反应应用程序,它利用 fetch 从/向 Rails 后端获取和发布/修补数据。我目前拥有它的方式,我只是将获取请求复制并粘贴到每个子组件中,但这似乎非常不合理。我想知道是否有办法在父组件(我的组件列表)中进行动态编码的获取/发布/补丁请求,而不必在每个需要它的组件中重写获取请求。以下是我正在使用的代码:

第一个子组件从文件 components/scripts/script8/page3.js 获取请求:

    state = {
        handleclick: {
        check_words: null,
        x_words: ''
        },
        text: {}
    }
        handleClick = (e, letter) => {
            if (letter === 'c'){
                this.setState({handleclick: {check_words: <Checked />, x_words: ''}})
            }
            else if (letter === 'x'){
                this.setState({handleclick: {check_words : null, x_words: "Go to the next page"}})
            }
        }

        handleScroll=()=>{
            window.scroll({top:0, behavior:'smooth'})
        }
        
        componentDidMount() {
            this.handleScroll()
            axios.get("http://localhost:3001/texts")
            .then(res => {
                const texts = res.data;
                for (const txt of texts){
                    if (txt.sheet === "8"){
                        this.setState({
                            text: {...this.state.text, [txt.id_tag]: txt}
                        })
                    }
                }
                  
        })
    }

        handleChange = (event) => {
            this.setState({text: {...this.state.text, [event.target.id]: {value: event.target.value, id_tag: event.target.id}}})
            if (event.target.id in this.state.text){
                axios.patch(`http://localhost:3001/texts/${this.state.text[event.target.id].id}`, {value: event.target.value, id_tag: event.target.id, sheet: "8"})
        }
            else {
                axios.post("http://localhost:3001/texts", {value: event.target.value, id_tag: event.target.id, sheet: "8" })
            }
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

来自 components/scripts/script3/page4.js 的第二个子组件获取请求:

    state = {
        text: {}
    }
    handleScroll=()=>{
        window.scroll({top:0,behavior:'smooth'})
    
    }
    componentDidMount() {
        this.handleScroll()
        axios.get("http://localhost:3001/texts")
        .then(res => {
            const texts = res.data;
            for (const txt of texts){
                if (txt.sheet === "3"){
                    this.setState({
                        text: {...this.state.text, [txt.id_tag]: txt}
                    })
                }
            }
              
    })
}

    handleChange = (event) => {
        this.setState({text: {...this.state.text, [event.target.id]: {value: event.target.value, id_tag: event.target.id}}})
        if (event.target.id in this.state.text){
            axios.patch(`http://localhost:3001/texts/${this.state.text[event.target.id].id}`, {value: event.target.value, id_tag: event.target.id, sheet: "3"})
    }
        else {
            axios.post("http://localhost:3001/texts", {value: event.target.value, id_tag: event.target.id, sheet: "3" })
        }
    }
    

    getValue = (id) => {
        for (const i in this.state.text){
            if (this.state.text[i].id_tag === id){
                return this.state.text[i].value;
            }
        }
        return ""
    }

请注意,唯一的区别是它是哪张纸。最重要的是,例如在 script8 中,两个文件可能具有相同的 fetch 函数。

当前我调用子组件的父组件:

class Script8List extends Component {

    state = {button_use: {button_back: false, button_forward: true}, 
    component_list: [<Page1 />, <Page2 />, <Page3 />, <Page4 />, <Page5 />, <Page6 />, <Page7 />, <Page8 />, <Page9 />, <Page10 />, <Page11 />, <Page12 />], 
    pagePos: 0}
    
    handleClick = (letter) => {//This determines which button was pressed
      if (letter === 'b'){
        this.setState((prevState) => ({pagePos: prevState.pagePos - 1}))
      }
      else {
        this.setState((prevState) => ({pagePos: prevState.pagePos + 1}))
      }
      
    }
    
    render() {
      return(
      <div className="Script8">{this.state.component_list[this.state.pagePos]}
        <div id="buttonDiv">
          {this.state.pagePos === 0 ? null :  <img alt="left arrow back" src={larrow} onClick={() => this.handleClick('b')} className="left arrow button"/>}
          {this.state.pagePos === this.state.component_list.length - 1 ? null :  <img alt="right arrow forward" src={rarrow} onClick={() => this.handleClick('f')} className="right arrow button"/>}
        </div>
        <h3 className="page_num">{this.state.pagePos + 1}</h3>
      </div>
      )
    }
  }

export default Script8List;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

这就是我希望父组件的样子:

class Script8List extends Component {

    state = {button_use: {button_back: false, button_forward: true}, 
    component_list: [<Page1 />, <Page2 />, <Page3 />, <Page4 />, <Page5 />, <Page6 />, <Page7 />, <Page8 />, <Page9 />, <Page10 />, <Page11 />, <Page12 />], 
    pagePos: 0}
    
    handleClick = (letter) => {//This determines which button was pressed
      if (letter === 'b'){
        this.setState((prevState) => ({pagePos: prevState.pagePos - 1}))
      }
      else {
        this.setState((prevState) => ({pagePos: prevState.pagePos + 1}))
      }
      
    }
    


handleClick = (e, letter) => {
    if (letter === 'c'){
        this.setState({handleclick: {check_words: <Checked />, x_words: ''}})
    }
    else if (letter === 'x'){
        this.setState({handleclick: {check_words : null, x_words: "Go to the next page"}})
    }
}

handleScroll=()=>{
    window.scroll({top:0, behavior:'smooth'})
}

componentDidMount() {
    this.handleScroll()
    axios.get("http://localhost:3001/texts")
    .then(res => {
        const texts = res.data;
        for (const txt of texts){
            if (txt.sheet === {current_sheet}){
                this.setState({
                    text: {...this.state.text, [txt.id_tag]: txt}
                })
            }
        }
          
})
}

handleChange = (event) => {
    this.setState({text: {...this.state.text, [event.target.id]: {value: event.target.value, id_tag: event.target.id}}})
    if (event.target.id in this.state.text){
        axios.patch(`http://localhost:3001/texts/${this.state.text[event.target.id].id}`, {value: event.target.value, id_tag: event.target.id, sheet: {current_sheet}})
}
    else {
        axios.post("http://localhost:3001/texts", {value: event.target.value, id_tag: event.target.id, sheet: {current_sheet} })
    }
}
    render() {
      return(
      <div className="Script8">{this.state.component_list[this.state.pagePos]}
        <div id="buttonDiv">
          {this.state.pagePos === 0 ? null :  <img alt="left arrow back" src={larrow} onClick={() => this.handleClick('b')} className="left arrow button"/>}
          {this.state.pagePos === this.state.component_list.length - 1 ? null :  <img alt="right arrow forward" src={rarrow} onClick={() => this.handleClick('f')} className="right arrow button"/>}
        </div>
        <h3 className="page_num">{this.state.pagePos + 1}</h3>
      </div>
      )
    }
  }

export default Script8List;

我唯一的问题是我不知道如何动态地执行此操作,以便我可以实时将信息发送到父组件,同时保持页面不变。部分问题是我会在文本框中发生变化的任何时候进行这些调用,因此我需要知道如何在两者之间进行交流。

【问题讨论】:

  • 不清楚您要完成什么。既然您在谈论父/子组件,您能否展示父子组件并准确描述问题出在哪里?您是否只是想为每个组件创建一个可重用的函数(如 useApi 挂钩?)
  • @windowsill 那是我的错,我将编辑主要帖子,以便您更好地理解。
  • 所有子组件都对/texts 使用相同的api 调用吗?即使您说您的问题与重复有关,您仍然没有显示任何重复。
  • 请更新您的问题以包含重复内容。
  • @windowsill 啊该死的好吧我更新了它以包含这个。

标签: javascript reactjs react-native axios fetch


【解决方案1】:

我真的不知道您的主要问题是什么,但是如果您看到一个父级与其子级共享 api 数据的最小示例,这可能会有所帮助。

const Parent = () => {
  const [apiResults, setApiResults] = useState([]);

  useEffect(() => onRefresh(), []);

  const onRefresh = () => axios.get().then(setApiResults);

  return <>
    <Child data={apiResults.find(r => r.page === 2)} onRefresh={onRefresh} />
    <Child data={apiResults.find(r => r.page === 3)} onRefresh={onRefresh} />
  <>;
};

const Child = ({data, onRefresh}) => {
  // ...
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-28
    • 2016-03-25
    • 2019-01-25
    • 2017-06-02
    • 2019-06-07
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多