ReactJS: चाइल्ड कंपोनेंट के अंदर पैरेंट पर सेटस्टैट


90

एक बच्चे के घटक से माता-पिता पर सेटस्टेट करने के लिए अनुशंसित पैटर्न क्या है।

var Todos = React.createClass({
  getInitialState: function() {
    return {
      todos: [
        "I am done",
        "I am not done"
      ]
    }
  },

  render: function() {
    var todos = this.state.todos.map(function(todo) {
      return <div>{todo}</div>;
    });

    return <div>
      <h3>Todo(s)</h3>
      {todos}
      <TodoForm />
    </div>;
  }
});

var TodoForm = React.createClass({
  getInitialState: function() {
    return {
      todoInput: ""
    }
  },

  handleOnChange: function(e) {
    e.preventDefault();
    this.setState({todoInput: e.target.value});
  },

  handleClick: function(e) {
    e.preventDefault();
    //add the new todo item
  },

  render: function() {
    return <div>
      <br />
      <input type="text" value={this.state.todoInput} onChange={this.handleOnChange} />
      <button onClick={this.handleClick}>Add Todo</button>
    </div>;
  }
});

React.render(<Todos />, document.body)

मेरे पास todo आइटमों की एक सरणी है जो कि माता-पिता की स्थिति में बनाए रखी जाती है। मैं माता पिता के राज्य का उपयोग और एक नया कार्य करने आइटम जोड़ने, से करना चाहते हैं TodoFormके handleClickघटक। मेरा विचार माता-पिता पर एक सेटस्टैट करना है, जो नए जोड़े गए टूडू आइटम को प्रस्तुत करेगा।


1
क्या यह मदद करती है stackoverflow.com/questions/24147331/… ?
धीरज

बस यहाँ स्पैम करें ... npmjs.com/package/react-event-observer
jujiyangasli

मुझे त्रुटि मिल रही हैsetState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the MyModal component.
मैट

मुझे वही त्रुटि मिल रही है जिसे मैं किसी अनमाउंट घटक पर सेट नहीं कर सकता। क्या इसके लिए वर्कअराउंड था?
केविन बर्टन

जवाबों:


81

अपने माता-पिता में, आप एक फ़ंक्शन बना सकते हैं जैसे addTodoItemकि आवश्यक सेटस्टेट करेंगे और फिर उस फ़ंक्शन को बाल घटक के लिए सहारा के रूप में पास करें।

var Todos = React.createClass({

  ...

  addTodoItem: function(todoItem) {
    this.setState(({ todos }) => ({ todos: { ...todos, todoItem } }));
  },

  render: function() {

    ...

    return <div>
      <h3>Todo(s)</h3>
      {todos}
      <TodoForm addTodoItem={this.addTodoItem} />
    </div>
  }
});

var TodoForm = React.createClass({
  handleClick: function(e) {
    e.preventDefault();
    this.props.addTodoItem(this.state.todoInput);
    this.setState({todoInput: ""});
  },

  ...

});

आप addTodoItemटोडोफॉर्म के हैंडल पर क्लिक कर सकते हैं । यह पैरेंट पर एक सेटस्टैट करेगा जो नए जोड़े गए टूडू आइटम को रेंडर करेगा। आशा है आपको आइडिया मिल जाएगा।

इधर उधर करना।


6
क्या है <<में ऑपरेटर this.state.todos << todoItem;यहां क्या कर?
गेब्रियल गैरेट

@zavtra लिटिल रूबी भ्रम चल रहा है मुझे लगता है
azium

7
this.stateसीधे तौर पर बगावत करना बुरा है । कार्यात्मक सेटस्टेट का उपयोग करने के लिए बेहतर है। reactjs.org/docs/react-component.html#setstate
Rohmer

2
फिडेल टूट गया है
हंटर नेल्सन

1
रिएक्ट हुक का उपयोग करके यह (अद्यतन) समाधान कैसे लागू किया जाएगा?
17

11

ये सभी अनिवार्य रूप से सही हैं, मैंने सोचा था कि मैं नए (ish) आधिकारिक प्रतिक्रिया प्रलेखन की ओर इशारा करूंगा जो मूल रूप से अनुशंसा करता है: -

किसी भी डेटा के लिए एक "सत्य का स्रोत" होना चाहिए जो एक प्रतिक्रिया एप्लिकेशन में बदलता है। आमतौर पर, राज्य को पहले उस घटक में जोड़ा जाता है जिसे रेंडर करने के लिए इसकी आवश्यकता होती है। फिर, यदि अन्य घटकों को भी इसकी आवश्यकता होती है, तो आप इसे अपने निकटतम सामान्य पूर्वज तक उठा सकते हैं। विभिन्न घटकों के बीच राज्य को सिंक करने की कोशिश करने के बजाय, आपको ऊपर-नीचे डेटा प्रवाह पर भरोसा करना चाहिए।

Https://reactjs.org/docs/lifting-state-up.html देखें । पेज एक उदाहरण के माध्यम से भी काम करता है।


8

आप मूल घटक में एक AddTodo फ़ंक्शन बना सकते हैं, इसे उस संदर्भ में बाँध सकते हैं, इसे चाइल्ड घटक को पास कर सकते हैं और इसे वहां से कॉल कर सकते हैं।

// in Todos
addTodo: function(newTodo) {
    // add todo
}

फिर, टोडोस.रेंडर में, आप करेंगे

<TodoForm addToDo={this.addTodo.bind(this)} />

टोडोफॉर्म में इसे कॉल करें

this.props.addToDo(newTodo);

यह बहुत उपयोगी था। bind(this)फंक्शन पास करने के समय, यह बिना किसी फंक्शन के एरर फेंक रहा था this.setState is not a function
प्रेट्र

6

उन लोगों के लिए जो रिएक्ट हुक के साथ राज्य बनाए हुए हैं useState, मैंने नीचे दिए गए डेमो स्लाइडर ऐप बनाने के लिए उपरोक्त सुझावों को अनुकूलित किया। डेमो ऐप में, चाइल्ड स्लाइडर घटक माता-पिता की स्थिति को बनाए रखता है।

डेमो भी useEffectहुक का उपयोग करता है । (और कम महत्वपूर्ण बात, useRefहुक)

import React, { useState, useEffect, useCallback, useRef } from "react";

//the parent react component
function Parent() {

  // the parentState will be set by its child slider component
  const [parentState, setParentState] = useState(0);

  // make wrapper function to give child
  const wrapperSetParentState = useCallback(val => {
    setParentState(val);
  }, [setParentState]);

  return (
    <div style={{ margin: 30 }}>
      <Child
        parentState={parentState}
        parentStateSetter={wrapperSetParentState}
      />
      <div>Parent State: {parentState}</div>
    </div>
  );
};

//the child react component
function Child({parentStateSetter}) {
  const childRef = useRef();
  const [childState, setChildState] = useState(0);

  useEffect(() => {
    parentStateSetter(childState);
  }, [parentStateSetter, childState]);

  const onSliderChangeHandler = e => {
  //pass slider's event value to child's state
    setChildState(e.target.value);
  };

  return (
    <div>
      <input
        type="range"
        min="1"
        max="255"
        value={childState}
        ref={childRef}
        onChange={onSliderChangeHandler}
      ></input>
    </div>
  );
};

export default Parent;

आप इस एप्लिकेशन को क्रिएट-रिएक्शन-ऐप के साथ उपयोग कर सकते हैं, और ऊपर दिए कोड के साथ App.js में सभी कोड बदल सकते हैं।
NicoWheat

नमस्ते, मैं प्रतिक्रिया करने के लिए नया हूं और सोच रहा था: क्या इसका उपयोग करना आवश्यक है useEffect? हमें माता-पिता और बच्चे दोनों की स्थिति में डेटा संग्रहीत करने की आवश्यकता क्यों है?
538ROMEO

1
उदाहरणों को यह दिखाने का इरादा नहीं है कि हमें माता-पिता और बच्चे दोनों में डेटा स्टोर करने की आवश्यकता क्यों है - अधिकांश समय आपको ज़रूरत नहीं है। लेकिन, अगर आपने खुद को ऐसी स्थिति में पाया है कि बच्चे को माता-पिता की स्थिति निर्धारित करनी चाहिए, तो यह है कि आप इसे कैसे कर सकते हैं। यदि आप मूल स्थिति को चाइल्डस्टैट के परिवर्तन के रूप में निर्धारित करना चाहते हैं तो उपयोग आवश्यक है।
NicoWheat

3
parentSetState={(obj) => { this.setState(obj) }}

4
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन समस्या को हल करने के तरीके के बारे में अतिरिक्त संदर्भ प्रदान करता है और यह समस्या को हल करता है ताकि उत्तर के दीर्घकालिक मूल्य में सुधार हो सके।
1:35 पर निक 3500

2

मुझे बच्चे के घटक से मूल घटक तक तर्क पारित करने के लिए निम्नलिखित कार्य और सरल समाधान मिला:

//ChildExt component
class ChildExt extends React.Component {
    render() {
        var handleForUpdate =   this.props.handleForUpdate;
        return (<div><button onClick={() => handleForUpdate('someNewVar')}>Push me</button></div>
        )
    }
}

//Parent component
class ParentExt extends React.Component {   
    constructor(props) {
        super(props);
        var handleForUpdate = this.handleForUpdate.bind(this);
    }
    handleForUpdate(someArg){
            alert('We pass argument from Child to Parent: \n' + someArg);   
    }

    render() {
        var handleForUpdate =   this.handleForUpdate;    
        return (<div>
                    <ChildExt handleForUpdate = {handleForUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentExt />,
        document.querySelector("#demo")
    );
}

JSFIDDLE को देखें


0

यदि आप माता-पिता के रूप में एक क्लास घटक के साथ काम कर रहे हैं, तो एक बच्चे को एक सेटस्टैट पास करने का एक बहुत ही सरल तरीका एक तीर फ़ंक्शन के भीतर से गुजर रहा है। यह काम करता है क्योंकि यह एक फहराया गया वातावरण सेट करता है जिसे पास किया जा सकता है:

class ClassComponent ... {

    modifyState = () =>{
        this.setState({...})   
    }
    render(){
          return <><ChildComponent parentStateModifier={modifyState} /></>
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.