ฉันจะเพิ่มแอททริบิวต์แบบมีเงื่อนไขลงไปในส่วนประกอบ React ได้อย่างไร


551

มีวิธีการที่จะเพิ่มคุณสมบัติให้กับองค์ประกอบการตอบสนองหากเงื่อนไขตรงหรือไม่?

ฉันควรจะเพิ่มแอตทริบิวต์ที่จำเป็นและ readOnly เพื่อสร้างองค์ประกอบตามการเรียก Ajax หลังจากแสดงผล แต่ฉันไม่เห็นวิธีแก้ปัญหานี้เนื่องจาก readOnly = "false" ไม่เหมือนกับการละเว้นแอตทริบิวต์ทั้งหมด

ตัวอย่างด้านล่างควรอธิบายสิ่งที่ฉันต้องการ แต่จะไม่ทำงาน (ข้อผิดพลาดในการแยกวิเคราะห์: ตัวระบุที่ไม่คาดคิด)

var React = require('React');

var MyOwnInput = React.createClass({
    render: function () {
        return (
            <div>
                <input type="text" onChange={this.changeValue} value={this.getValue()} name={this.props.name}/>
            </div>
        );
    }
});

module.exports = React.createClass({
    getInitialState: function () {
        return {
            isRequired: false
        }
    },
    componentDidMount: function () {
        this.setState({
            isRequired: true
        });
    },
    render: function () {
        var isRequired = this.state.isRequired;

        return (
            <MyOwnInput name="test" {isRequired ? "required" : ""} />
        );
    }
});

1
อาจเป็นหนึ่งความคิดเห็นช่วยใครบางคนฉันพบว่าตอบสนอง 16.7 ไม่แสดงผลและอัปเดตแอตทริบิวต์ html ขององค์ประกอบหากคุณเปลี่ยนเฉพาะพวกเขาในร้านค้า (fe redux) และเชื่อมโยงกับองค์ประกอบ ซึ่งหมายความว่าองค์ประกอบมี fe aria-modal=trueคุณผลักดันการเปลี่ยนแปลง (เป็นเท็จ) ไปยังที่เก็บของคุณลักษณะaria / dataแต่ไม่มีอะไรเปลี่ยนแปลง (เช่นเนื้อหาของส่วนประกอบหรือคลาสหรือตัวแปรในนั้น) เนื่องจากผลลัพธ์ ReactJs จะไม่อัปเดตaria / data attrs ในส่วนประกอบนั้น ฉันยุ่งเกี่ยวกับทั้งวันเพื่อตระหนักว่า
AlexNikonov

คำตอบ:


535

เห็นได้ชัดว่าสำหรับคุณลักษณะบางอย่าง React นั้นฉลาดพอที่จะละเว้นแอตทริบิวต์นั้นได้หากค่าที่คุณส่งไปนั้นไม่ใช่ความจริง ตัวอย่างเช่น:

var InputComponent = React.createClass({
    render: function() {
        var required = true;
        var disabled = false;

        return (
            <input type="text" disabled={disabled} required={required} />
        );
    }
});

จะส่งผลให้:

<input type="text" required>

อัปเดต:หากใครอยากรู้ว่าสิ่งนี้เกิดขึ้นได้อย่างไรคุณสามารถค้นหารายละเอียดได้ในซอร์สโค้ดของ ReactDOM โดยเฉพาะที่บรรทัดที่30และ167ของไฟล์DOMProperty.js


45
โดยทั่วไปnullหมายถึง "ทำตัวเหมือนฉันไม่ได้ระบุเลย" สำหรับคุณลักษณะบูลีน dom จริง / เท็จเป็นที่ต้องการมากกว่าการทำซ้ำชื่อแอตทริบิวต์ / เท็จเช่น<input disabled>คอมไพล์ไปReact.createElement('input', {disabled: true})
Brigand

ฉันเห็นด้วย. ฉันทำซ้ำชื่อเพราะฉันมีปัญหาในอดีตกับเบราว์เซอร์บางอย่างและนิสัยติดกับฉันมากที่ฉันเพิ่มใน="required"ส่วนด้วยตนเอง Chrome จริง ๆ แล้วแสดงคุณลักษณะเฉพาะโดยไม่มีค่า
juandemarco

8
readonlyไม่เคยได้รับเพิ่มเพราะปฏิกิริยาตอบสนองคาดว่าจะมีคุณลักษณะreadOnly(ด้วยตัวพิมพ์ใหญ่ O)
Max

8
ขอบคุณ! ตรวจสอบให้แน่ใจว่าค่าไม่ใช่แค่สตริงว่างหรือศูนย์สิ่งเหล่านี้อาจไม่ถูกลบ alt={props.alt || null}ตัวอย่างเช่นคุณสามารถส่งค่าเช่นนี้และมันควรจะให้แน่ใจว่ามันจะถูกลบออกถ้ามันประเมินเท็จ
Jake

5
ขอบคุณ @Jake ฉันได้ลองตั้งค่าคุณลักษณะเป็นfalseแต่nullให้แน่ใจว่าคุณลักษณะนั้นถูกลบออกจริง
Nathan Arthur

386

คำตอบของ juandemarcoนั้นถูกต้อง แต่นี่เป็นอีกทางเลือกหนึ่ง

สร้างวัตถุตามที่คุณต้องการ:

var inputProps = {
  value: 'foo',
  onChange: this.handleChange
};

if (condition)
  inputProps.disabled = true;

แสดงผลด้วยสเปรดหรือผ่านอุปกรณ์ประกอบฉากอื่นด้วย

<input
    value="this is overridden by inputProps"
    {...inputProps}
    onChange={overridesInputProps}
 />

14
นี่เป็นประโยชน์อย่างมากโดยเฉพาะอย่างยิ่งเมื่อเพิ่มคุณสมบัติหลายอย่างตามเงื่อนไข (และโดยส่วนตัวแล้วฉันไม่รู้ว่ามันสามารถทำได้ด้วยวิธีนี้)
juandemarco

1
สง่างามมาก แต่ไม่ควรใส่ inputProps.disabled = true?
Joppe

ง่ายมากฉันทำให้โค้ดอ่านง่ายขึ้นโดยไม่ต้องมีหลายเงื่อนไข
Naveen Kumar PG

หากใครสนใจเกี่ยวกับความหมายที่แม่นยำของ "น้ำตาล" คุณสามารถดูสคริปต์ที่. jsx ของคุณถูกแปลงเป็นคุณจะเห็นว่า_extendsมีการเพิ่มฟังก์ชั่นซึ่งจะ (ภายใต้สถานการณ์ปกติ) นำสิ่งที่propsสร้างขึ้นมาจาก "แอตทริบิวต์ปกติ" Object.assign(props, inputProps)และนำไปใช้
นาธาน Chappell

299

นี่คือตัวอย่างของการใช้เงินทุนของButtonผ่านReact-Bootstrap (เวอร์ชั่น 0.32.4):

var condition = true;

return (
  <Button {...(condition ? {bsStyle: 'success'} : {})} />
);

ทั้งนี้ขึ้นอยู่กับเงื่อนไขอย่างใดอย่างหนึ่ง{bsStyle: 'success'}หรือ{}จะถูกส่งกลับ ผู้ประกอบการแพร่กระจายจะกระจายคุณสมบัติของวัตถุที่ส่งคืนไปยังButtonส่วนประกอบ ในกรณีที่เป็นเท็จเนื่องจากไม่มีคุณสมบัติบนวัตถุที่ส่งคืนจะไม่มีการส่งผ่านไปยังคอมโพเนนต์


อีกทางเลือกหนึ่งตามความคิดเห็นของ Andy Polhill :

var condition = true;

return (
  <Button bsStyle={condition ? 'success' : undefined} />
);

ความแตกต่างเล็ก ๆ เท่านั้นที่อยู่ในตัวอย่างที่สององค์ประกอบภายใน<Button/>ของpropsวัตถุจะมีกุญแจที่มีค่าของbsStyleundefined


5
@Punit ตัวดำเนินการสเปรดมีลำดับความสำคัญต่ำกว่าตัวดำเนินการตามเงื่อนไขดังนั้นเงื่อนไขจะถูกประเมินก่อน (อย่างใดอย่างหนึ่ง{bsStyle: 'success'}หรือ{}ผลลัพธ์จากมัน) จากนั้นวัตถุนั้นจะถูกกระจาย
Victor Zamanian

5
ต่อไปนี้จะทำเช่นเดียวกัน <Button bsStyle={ condition ? 'success': undefined } /> ฉันจะหาไวยากรณ์ได้ง่ายขึ้นเล็กน้อยการผ่านundefinedจะไม่ใช้คุณสมบัติ
Andy Polhill

3
@AndyPolhill ดูดีกับผมและง่ายมากที่จะอ่านรหัสที่แตกต่างเล็ก ๆ เพียงอย่างเดียวคือว่าในตัวอย่างรหัสของคุณส่วนประกอบภายใน<Button/>ของpropsวัตถุจะมีกุญแจที่มีค่าของbsStyle undefined
Arman Yeghiazaryan

@AndyPolhill เหตุผลที่ไวยากรณ์ดูเหมือนอ่านยากขึ้นเพราะไม่มีวงเล็บบางส่วนซึ่งทำให้ตัวอย่างดูแปลกตาและเข้าใจยากกว่า การแก้ไขตัวอย่างเพื่อเพิ่มวงเล็บ
Govind Rai

1
วิธีแรกทำงานได้อย่างสมบูรณ์แบบสำหรับฉันขอบคุณ
Liran H

86

นี่คือทางเลือก

var condition = true;

var props = {
  value: 'foo',
  ...( condition && { disabled: true } )
};

var component = <div { ...props } />;

หรือรุ่นอินไลน์

var condition = true;

var component = (
  <div
    value="foo"
    { ...( condition && { disabled: true } ) } />
);

9
ฉันชอบวิธีนี้มันทำให้ฉันเท่ห์ในหมู่เพื่อนร่วมงานของฉัน ล้อเล่นกันจากรูปลักษณ์ของมันอุปกรณ์ประกอบฉากเพิ่งถูกส่งผ่านเป็นคู่ค่าคีย์หลังจากนั้นถูกต้องหรือไม่
JohnnyQ

1
หากconditionเป็นเท็จสิ่งนี้จะพยายามขยาย / วนซ้ำกับเท็จซึ่งฉันคิดว่าไม่ถูกต้อง
Lars Nyström

1
@ LarsNyströmนั่นสมเหตุสมผล ผู้ประกอบการแพร่กระจายยอมรับเฉพาะ iterables ที่falseไม่ได้เป็นหนึ่ง เพียงตรวจสอบกับ Babel สิ่งนี้ใช้ได้กับมันเมื่อconditionประเมินว่าเป็นเท็จเนื่องจากวิธีบาเบลใช้ตัวดำเนินการ แม้ว่าวิธีแก้ปัญหาเล็กน้อยอาจเป็น...( condition ? { disabled: true } : {} )ไปได้ ขอบคุณสำหรับข้อมูลที่ดีนี้!
ซีซัน

+1 วิธีการนี้เป็นสิ่งจำเป็นหากคุณต้องการส่งออกdata-*หรือaria-*คุณลักษณะตามเงื่อนไขเนื่องจากเป็นกรณีพิเศษใน JSX ดังนั้นdata-my-conditional-attr={ false }จะส่งออกdata-my-conditional-attr="false"แทนที่จะละเว้นแอตทริบิวต์ facebook.github.io/react/docs/dom-elements.html
ptim

32

นี่คือวิธีที่ฉันทำ

ด้วยเงื่อนไข :

<Label
    {...{
      text: label,
      type,
      ...(tooltip && { tooltip }),
      isRequired: required
    }}
/>

ฉันยังคงชอบใช้วิธีปกติในการส่งอุปกรณ์ประกอบฉากลงเพราะมันสามารถอ่านได้มากขึ้น (ตามความเห็นของฉัน) ในกรณีที่ไม่มีเงื่อนไขใด ๆ

ไม่มีเงื่อนไข :

<Label text={label} type={type} tooltip={tooltip} isRequired={required} />

คุณช่วยอธิบายได้...(tooltip && { tooltip }),ไหมว่าชิ้นส่วนนี้ทำงานอย่างไร มันใช้งานได้กับส่วนประกอบ แต่เมื่อฉันพยายามใช้สิ่งนี้ในรหัสฉันได้รับข้อผิดพลาดซึ่งหมายความว่าฉันพยายามกระจายค่าที่ไม่สามารถทำซ้ำได้
skwisgaar

อาจจะเป็นเพราะจะกลับเท็จดังนั้นโอกาสที่คุณมีการแพร่กระจายบนเช่นเท็จfalseyValue && {} ...(false)ดีกว่าที่จะใช้การแสดงออกแบบเต็มดังนั้นการแพร่กระจายยังคงทำงาน ...(condition ? {foo: 'bar'} : {})
lfender6445

19

คุณสามารถใช้ทางลัดเดียวกันซึ่งใช้เพื่อเพิ่ม / ลบ (ส่วนประกอบของ) ส่วนประกอบ ( {isVisible && <SomeComponent />})

class MyComponent extends React.Component {
  render() {
    return (
      <div someAttribute={someCondition && someValue} />
    );
  }
}

3
ถ้า someConditionเป็นจริง แต่someValueเป็นเท็จ (เช่นfalseตัวเองหรือ0อื่น ๆ ) คุณลักษณะนี้ยังรวมอยู่หรือไม่ สิ่งนี้มีความสำคัญหากจำเป็นต้องระบุค่าที่ผิดพลาดอย่างชัดเจนเช่น0สำหรับแอตทริบิวต์พิกัด ฯลฯ
Andrew Willems

โดยปกติแล้วแอตทริบิวต์จะถูกละเว้น แต่ไม่ใช่ในกรณีของdata-*และaria-*ดูความคิดเห็นของฉันด้านบน หากคุณอ้างถึงค่าหรือโยนมันเป็นสตริงแอตทริบิวต์จะแสดง: เช่นsomeAttr={ `${falsyValue}` }สามารถแสดงผลได้someAttr="false"
ptim

19

สมมติว่าเราต้องการเพิ่มคุณสมบัติที่กำหนดเอง (โดยใช้ aria- * หรือ data- *) หากเงื่อนไขเป็นจริง:

{...this.props.isTrue && {'aria-name' : 'something here'}}

สมมติว่าเราต้องการเพิ่มคุณสมบัติสไตล์หากเงื่อนไขเป็นจริง:

{...this.props.isTrue && {style : {color: 'red'}}}

10

หากคุณใช้ ECMAScript 6 คุณสามารถเขียนได้เช่นนี้

// First, create a wrap object.
const wrap = {
    [variableName]: true
}
// Then, use it
<SomeComponent {...{wrap}} />

7

สิ่งนี้จะได้ผลเนื่องจากสถานะของคุณจะเปลี่ยนไปหลังจากการเรียก Ajax และองค์ประกอบหลักจะแสดงผลอีกครั้ง

render : function () {
    var item;
    if (this.state.isRequired) {
        item = <MyOwnInput attribute={'whatever'} />
    } else {
        item = <MyOwnInput />
    }
    return (
        <div>
            {item}
        </div>
    );
}

3

ในการตอบสนองคุณสามารถสร้างการแสดงผลแบบมีเงื่อนไข แต่ยังรวมถึงคุณลักษณะของพวกเขาเช่นอุปกรณ์ประกอบฉาก className, id และอื่น ๆ

ในการตอบสนองเป็นวิธีปฏิบัติที่ดีมากในการใช้ตัวดำเนินการประกอบไปด้วยซึ่งสามารถช่วยให้คุณสร้างองค์ประกอบได้

ตัวอย่างยังแสดงวิธีการแสดงผล Component และคุณลักษณะสไตล์ของมันแบบมีเงื่อนไข

นี่คือตัวอย่างง่ายๆ:

class App extends React.Component {
  state = {
    isTrue: true
  };

  render() {
    return (
      <div>
        {this.state.isTrue ? (
          <button style={{ color: this.state.isTrue ? "red" : "blue" }}>
            I am rendered if TRUE
          </button>
        ) : (
          <button>I am rendered if FALSE</button>
        )}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>


สิ่งนี้อาจยุ่งเหยิงกับแอตทริบิวต์มากมาย ฉันชอบตัวแปรสเปรดที่ดีกว่า
Remi Sture

ใช่คุณพูดถูก แต่สำหรับคนที่ต้องการภาพรวมฉันจะทำอีกตัวอย่างหนึ่ง แต่ต้องการให้เรื่องง่าย ๆ
Juraj

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.